[med-svn] [Git][med-team/twopaco][upstream] New upstream version 1.0.0+dfsg
Andrius Merkys (@merkys)
gitlab at salsa.debian.org
Thu Sep 29 07:23:51 BST 2022
Andrius Merkys pushed to branch upstream at Debian Med / twopaco
Commits:
58de084d by Andrius Merkys at 2022-09-29T01:32:25-04:00
New upstream version 1.0.0+dfsg
- - - - -
13 changed files:
- NEWS.md
- README.md
- src/CMakeLists.txt
- src/common/streamfastaparser.cpp
- src/common/streamfastaparser.h
- src/graphconstructor/CMakeLists.txt
- src/graphconstructor/assemblyedgeconstructor.h
- src/graphconstructor/bifurcationstorage.h
- src/graphconstructor/common.h
- src/graphconstructor/constructor.cpp
- src/graphconstructor/vertexenumerator.h
- src/graphdump/CMakeLists.txt
- src/graphdump/graphdump.cpp
Changes:
=====================================
NEWS.md
=====================================
@@ -1,3 +1,7 @@
+TwoPaCo 1.0.0
+=============
+* Added support of the newer version of TBB library
+
TwoPaCo 0.9.4
=============
* Added the installation scripts
=====================================
README.md
=====================================
@@ -1,6 +1,6 @@
-TwoPaCo 0.9.4
+TwoPaCo 1.0.0
-Release date: 25th September 2020
+Release date: 29th September 2022
=============================
Authors
=====================================
src/CMakeLists.txt
=====================================
@@ -1,6 +1,8 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.15)
project(root)
+set(CMAKE_CXX_STANDARD 14)
set(CMAKE_BUILD_TYPE RELEASE)
add_subdirectory(graphdump)
add_subdirectory(graphconstructor)
include(CPack)
+set(THREADS_PREFER_PTHREAD_FLAG ON)
=====================================
src/common/streamfastaparser.cpp
=====================================
@@ -1,5 +1,6 @@
#include <sstream>
#include <algorithm>
+#include <mutex>
#include "streamfastaparser.h"
=====================================
src/common/streamfastaparser.h
=====================================
@@ -5,7 +5,6 @@
#include <fstream>
#include <stdexcept>
#include <algorithm>
-#include <tbb/mutex.h>
#include <iostream>
#include <memory>
@@ -131,7 +130,7 @@ namespace TwoPaCo
size_t seqId_;
size_t start_;
size_t pieceId_;
- tbb::mutex mutex_;
+ std::mutex mutex_;
size_t overlapSize_;
std::ifstream in_;
std::string overlapBuffer_;
=====================================
src/graphconstructor/CMakeLists.txt
=====================================
@@ -1,17 +1,14 @@
project(twopaco CXX)
-cmake_minimum_required(VERSION 2.8)
set(CMAKE_PROJECT_NAME twopaco)
-if(CMAKE_COMPILER_IS_GNUCXX)
- list(APPEND "CMAKE_CXX_FLAGS" "-std=c++11 -lstdc++")
-endif()
+set(CMAKE_CXX_STANDARD 14)
add_executable(twopaco ../common/dnachar.cpp constructor.cpp concurrentbitvector.cpp compressedstring.cpp ../common/streamfastaparser.cpp test.cpp vertexenumerator.cpp ../common/spooky/SpookyV2.cpp common.cpp)
link_directories(${TBB_LIB_DIR})
include_directories(${twopaco_SOURCE_DIR} ${TBB_INCLUDE_DIR} "../common")
-target_link_libraries(twopaco "tbb" )
+target_link_libraries(twopaco "tbb" "tbbmalloc" "tbbmalloc_proxy" "pthread" )
install(TARGETS twopaco RUNTIME DESTINATION bin)
-set(CPACK_PACKAGE_VERSION_MAJOR "0")
-set(CPACK_PACKAGE_VERSION_MINOR "9")
-set(CPACK_PACKAGE_VERSION_PATCH "4")
+set(CPACK_PACKAGE_VERSION_MAJOR "1")
+set(CPACK_PACKAGE_VERSION_MINOR "0")
+set(CPACK_PACKAGE_VERSION_PATCH "0")
=====================================
src/graphconstructor/assemblyedgeconstructor.h
=====================================
@@ -8,7 +8,7 @@ namespace TwoPaCo
class AssemblyEdgeConstructor
{
public:
- AssemblyEdgeConstructor(const std::vector<std::string> & inputFileName, const std::string & marksFileName, const VertexEnumerator & vertexEnumerator) :
+ AssemblyEdgeConstructor(const std::vector<std::string> & inputFileName, const std::string & marksFileName, const VertexEnumerator & vertexEnumerator) :
vertexEnumerator_(vertexEnumerator)
{
int64_t vertexLength = vertexEnumerator_.GetHashSeed().VertexLength();
@@ -20,11 +20,11 @@ namespace TwoPaCo
JunctionPositionReader junctionReader(marksFileName);
// std::unique_ptr<ConcurrentBitVector> bloomFilter = vertexEnumerator_.ReloadBloomFilter();
for (std::string chr; chrReader.NextChr(chr); chrNumber++)
- {
+ {
//Read the current vector of junction marks. Notice: should be done in order!
junctionMark.push_back(std::vector<bool>(chr.size(), false));
junctionReader.RestoreVector(junctionMark.back(), chrNumber);
- //Init hash function
+ //Init hash function
VertexRollingHash hash(vertexEnumerator.GetHashSeed(), chr.begin(), vertexEnumerator.GetHashSeed().HashFunctionsNumber());
for (int64_t i = 0; i <= int64_t(chr.size()) - edgeLength; i++)
{
@@ -35,7 +35,7 @@ namespace TwoPaCo
{
assert(IsIngoingEdgeInBloomFilter(hash, *bloomFilter, chr[i - 1]));
}
-
+
//Check the if the vertex is a junction
if (vertexEnumerator_.GetId(vertex) != INVALID_VERTEX)
{
@@ -49,7 +49,7 @@ namespace TwoPaCo
}
}
}
-
+
private:
const VertexEnumerator & vertexEnumerator_;
DISALLOW_COPY_AND_ASSIGN(AssemblyEdgeConstructor);
@@ -58,4 +58,4 @@ namespace TwoPaCo
}
-#endif
\ No newline at end of file
+#endif
=====================================
src/graphconstructor/bifurcationstorage.h
=====================================
@@ -1,6 +1,7 @@
#ifndef _BIFURCATION_STORAGE_H_
#define _BIFURCATION_STORAGE_H_
+#include "oneapi/tbb/task_arena.h"
#include "common.h"
#include "compressedstring.h"
@@ -34,7 +35,7 @@ namespace TwoPaCo
}
size_t hashFunctionNumber = 3;
- bitsPower = max(bitsPower, size_t(24));
+ bitsPower = std::max(static_cast<size_t>(bitsPower), size_t(24));
bifurcationFilter_.assign(uint64_t(1) << bitsPower, false);
hashFunction_.resize(hashFunctionNumber);
for (HashFunctionPtr & ptr : hashFunction_)
@@ -61,8 +62,13 @@ namespace TwoPaCo
}
}
- tbb::task_scheduler_init init(threads);
- tbb::parallel_sort(bifurcationKey_.begin(), bifurcationKey_.end(), DnaString::Less);
+
+ // Create the custom task_arena with four threads
+ oneapi::tbb::task_arena arena(threads);
+
+ arena.execute([this]{
+ oneapi::tbb::parallel_sort(this->bifurcationKey_.begin(), this->bifurcationKey_.end(), DnaString::Less);
+ });
}
int64_t GetId(std::string::const_iterator pos) const
@@ -161,4 +167,4 @@ namespace TwoPaCo
};
}
-#endif
\ No newline at end of file
+#endif
=====================================
src/graphconstructor/common.h
=====================================
@@ -11,7 +11,7 @@
#include <functional>
#include <dnachar.h>
-#include <tbb/concurrent_queue.h>
+#include "oneapi/tbb/concurrent_queue.h"
namespace TwoPaCo
{
@@ -38,14 +38,14 @@ namespace TwoPaCo
static const size_t TASK_SIZE = 32;
#else
static const size_t TASK_SIZE = 1 << 19;
-#endif
+#endif
static const size_t GAME_OVER = SIZE_MAX;
Task() {}
Task(uint64_t seqId, uint64_t start, uint64_t piece, uint64_t offset, bool isFinal, std::string && str) :
seqId(seqId), start(start), piece(piece), offset(offset), isFinal(isFinal), str(std::move(str)) {}
};
- typedef tbb::concurrent_bounded_queue<Task> TaskQueue;
+ typedef oneapi::tbb::concurrent_bounded_queue<Task> TaskQueue;
typedef std::unique_ptr<TaskQueue> TaskQueuePtr;
}
=====================================
src/graphconstructor/constructor.cpp
=====================================
@@ -14,6 +14,7 @@
#include <sstream>
#include <tclap/CmdLine.h>
+#include "oneapi/tbb/scalable_allocator.h"
#include "test.h"
#include "assemblyedgeconstructor.h"
@@ -55,7 +56,7 @@ int main(int argc, char * argv[])
OddConstraint constraint;
try
{
- TCLAP::CmdLine cmd("Program for construction of the condensed de Bruijn graph from complete genomes", ' ', "0.9.4");
+ TCLAP::CmdLine cmd("Program for construction of the condensed de Bruijn graph from complete genomes", ' ', "1.0.0");
TCLAP::ValueArg<unsigned int> kvalue("k",
"kvalue",
@@ -187,5 +188,32 @@ int main(int argc, char * argv[])
return 1;
}
+
+ // NOTE: why do this here? Well, this is to
+ // fix the OSX build under [bioconda](https://bioconda.github.io).
+ // Specifically, when the `scalable_allocation_command` is called
+ // it can result in a segmentation fault if no prior allocation had
+ // been made because of the invalid state of the underlying pointer
+ // examined by `scalable_allocation_command`. In reality, this shouldn't
+ // happen because of the static initalization of that pointer, but it
+ // does (on older OSX platforms). So, here we will allocate a small
+ // amount of memory (1k), which will force the scalable allocator
+ // to initalize itself properly. Then, we will immediately free
+ // this memory. Then we will make the call to `scalable_allocation_command`.
+ // This ensures (for the cost of one extra allocation call) that the
+ // call to `scalable_allocation_command` works across all platforms on
+ // which we need to build.
+ void* salloc = scalable_malloc(1024);
+
+ if (salloc == nullptr) {
+ std::cerr << "TwoPaCo::buildGraphMain:: couldn't allocate using scalable_malloc!" << std::endl;
+ } else {
+ std::cerr << "TwoPaCo::buildGraphMain:: allocated with scalable_malloc; freeing." << std::endl;
+ scalable_free(salloc);
+
+ std::cerr << "TwoPaCo::buildGraphMain:: Calling scalable_allocation_command(TBBMALLOC_CLEAN_ALL_BUFFERS, 0);" << std::endl;
+ scalable_allocation_command(TBBMALLOC_CLEAN_ALL_BUFFERS, 0);
+ }
+
return 0;
}
=====================================
src/graphconstructor/vertexenumerator.h
=====================================
@@ -9,15 +9,12 @@
#include <sstream>
#include <unordered_map>
-#include <tbb/tbb.h>
-#include <tbb/mutex.h>
-#include <tbb/compat/thread>
-#include <tbb/spin_rw_mutex.h>
-#include <tbb/blocked_range.h>
-#include <tbb/parallel_sort.h>
-#include <tbb/parallel_reduce.h>
-#include <tbb/task_scheduler_init.h>
-#include <tbb/concurrent_unordered_set.h>
+#include "tbb/tbb.h"
+#include "oneapi/tbb/spin_rw_mutex.h"
+#include "oneapi/tbb/blocked_range.h"
+#include "oneapi/tbb/parallel_sort.h"
+#include "oneapi/tbb/parallel_reduce.h"
+#include "oneapi/tbb/concurrent_unordered_set.h"
#include <junctionapi.h>
@@ -94,7 +91,7 @@ namespace TwoPaCo
}
};
- typedef tbb::concurrent_unordered_set<Occurence, OccurenceHash, OccurenceEquality> OccurenceSet;
+ typedef oneapi::tbb::concurrent_unordered_set<Occurence, OccurenceHash, OccurenceEquality> OccurenceSet;
public:
@@ -162,7 +159,7 @@ namespace TwoPaCo
std::ostream & logFile = std::cerr;
#endif
- tbb::mutex errorMutex;
+ std::mutex errorMutex;
std::unique_ptr<std::runtime_error> error;
size_t edgeLength = vertexLength + 1;
@@ -183,7 +180,7 @@ namespace TwoPaCo
if (rounds > 1)
{
logStream << "Splitting the input kmers set..." << std::endl;
- std::vector<std::unique_ptr<tbb::tbb_thread> > workerThread(threads);
+ std::vector<std::unique_ptr<std::thread> > workerThread(threads);
binCounter = new std::atomic<uint32_t>[BINS_COUNT];
std::fill(binCounter, binCounter + BINS_COUNT, 0);
ConcurrentBitVector bitVector(realSize);
@@ -195,7 +192,7 @@ namespace TwoPaCo
vertexLength,
*taskQueue[i],
binCounter);
- workerThread[i].reset(new tbb::tbb_thread(worker));
+ workerThread[i].reset(new std::thread(worker));
}
DistributeTasks(fileName, edgeLength, taskQueue, error, errorMutex, logFile, offset, offsetFill);
@@ -265,7 +262,7 @@ namespace TwoPaCo
logStream << "Round " << round << ", " << low << ":" << high << std::endl;
logStream << "Pass\tFilling\tFiltering" << std::endl << "1\t";
{
- std::vector<std::unique_ptr<tbb::tbb_thread> > workerThread(threads);
+ std::vector<std::unique_ptr<std::thread> > workerThread(threads);
for (size_t i = 0; i < workerThread.size(); i++)
{
FilterFillerWorker worker(low,
@@ -274,7 +271,7 @@ namespace TwoPaCo
std::ref(bitVector),
edgeLength,
std::ref(*taskQueue[i]));
- workerThread[i].reset(new tbb::tbb_thread(worker));
+ workerThread[i].reset(new std::thread(worker));
}
DistributeTasks(fileName, edgeLength, taskQueue, error, errorMutex, logFile, offset, offsetFill);
@@ -290,7 +287,7 @@ namespace TwoPaCo
}
//bitVector.WriteToFile(filterDumpFile_);
- tbb::mutex maskStorageMutex;
+ std::mutex maskStorageMutex;
std::ofstream maskStorage(CandidateMaskFileName(tmpDirName, round).c_str(), ios::binary);
if (!maskStorage)
{
@@ -300,7 +297,7 @@ namespace TwoPaCo
logStream << time(0) - mark << "\t";
mark = time(0);
{
- std::vector<std::unique_ptr<tbb::tbb_thread> > workerThread(threads);
+ std::vector<std::unique_ptr<std::thread> > workerThread(threads);
for (size_t i = 0; i < workerThread.size(); i++)
{
CandidateCheckingWorker worker(std::make_pair(low, high),
@@ -316,7 +313,7 @@ namespace TwoPaCo
error,
errorMutex);
- workerThread[i].reset(new tbb::tbb_thread(worker));
+ workerThread[i].reset(new std::thread(worker));
}
DistributeTasks(fileName, vertexLength + 1, taskQueue, error, errorMutex, logFile, offset, offsetFill);
@@ -335,18 +332,18 @@ namespace TwoPaCo
}
mark = time(0);
- tbb::spin_rw_mutex mutex;
+ oneapi::tbb::spin_rw_mutex mutex;
logStream << "2\t";
OccurenceSet occurenceSet(1 << 20);
{
- tbb::mutex maskStorageMutex;
+ std::mutex maskStorageMutex;
inMaskStorage[round] = new std::ifstream(CandidateMaskFileName(tmpDirName, round).c_str(), ios::binary);
if (!(*inMaskStorage[round]))
{
throw std::runtime_error("Can't open a temporary file");
}
- std::vector<std::unique_ptr<tbb::tbb_thread> > workerThread(threads);
+ std::vector<std::unique_ptr<std::thread> > workerThread(threads);
for (size_t i = 0; i < workerThread.size(); i++)
{
CandidateFinalFilteringWorker worker(hashFunctionSeed_,
@@ -361,7 +358,7 @@ namespace TwoPaCo
error,
errorMutex);
- workerThread[i].reset(new tbb::tbb_thread(worker));
+ workerThread[i].reset(new std::thread(worker));
}
DistributeTasks(fileName, vertexLength + 1, taskQueue, error, errorMutex, logFile, offset, offsetFill);
@@ -415,14 +412,14 @@ namespace TwoPaCo
mark = time(0);
std::atomic<uint64_t> occurence;
- tbb::mutex currentStubVertexMutex;
+ std::mutex currentStubVertexMutex;
std::atomic<uint64_t> currentPiece;
uint64_t currentStubVertexId = verticesCount + 42;
JunctionPositionWriter posWriter(outFileNamePrefix);
occurence = currentPiece = 0;
{
- tbb::mutex inMaskStorageMutex;
- std::vector<std::unique_ptr<tbb::tbb_thread> > workerThread(threads);
+ std::mutex inMaskStorageMutex;
+ std::vector<std::unique_ptr<std::thread> > workerThread(threads);
for (size_t i = 0; i < workerThread.size(); i++)
{
EdgeConstructionWorker worker(vertexLength,
@@ -439,7 +436,7 @@ namespace TwoPaCo
error,
errorMutex);
- workerThread[i].reset(new tbb::tbb_thread(worker));
+ workerThread[i].reset(new std::thread(worker));
}
DistributeTasks(fileName, vertexLength + 1, taskQueue, error, errorMutex, logFile, offset, offsetFill);
@@ -490,7 +487,7 @@ namespace TwoPaCo
return ss.str();
}
- static void ReportError(tbb::mutex & errorMutex, std::unique_ptr<std::runtime_error> & error, const std::string & msg)
+ static void ReportError(std::mutex & errorMutex, std::unique_ptr<std::runtime_error> & error, const std::string & msg)
{
errorMutex.lock();
if (error == 0)
@@ -596,9 +593,9 @@ namespace TwoPaCo
std::atomic<uint64_t> & marksCount,
size_t round,
std::ofstream & maskStorage,
- tbb::mutex & maskStorageMutex,
+ std::mutex & maskStorageMutex,
std::unique_ptr<std::runtime_error> & error,
- tbb::mutex & errorMutex) : bound(bound), hashFunction(hashFunction), bitVector(bitVector), vertexLength(vertexLength), taskQueue(taskQueue),
+ std::mutex & errorMutex) : bound(bound), hashFunction(hashFunction), bitVector(bitVector), vertexLength(vertexLength), taskQueue(taskQueue),
tmpDirectory(tmpDirectory), marksCount(marksCount), maskStorage(maskStorage), maskStorageMutex(maskStorageMutex), error(error), errorMutex(errorMutex), round(round)
{
@@ -699,9 +696,9 @@ namespace TwoPaCo
std::atomic<uint64_t> & marksCount;
size_t round;
std::ofstream & maskStorage;
- tbb::mutex & maskStorageMutex;
+ std::mutex & maskStorageMutex;
std::unique_ptr<std::runtime_error> & error;
- tbb::mutex & errorMutex;
+ std::mutex & errorMutex;
};
@@ -713,13 +710,13 @@ namespace TwoPaCo
size_t vertexLength,
TaskQueue & taskQueue,
OccurenceSet & occurenceSet,
- tbb::spin_rw_mutex & mutex,
+ oneapi::tbb::spin_rw_mutex & mutex,
const std::string & tmpDirectory,
size_t round,
std::ifstream & maskStorage,
- tbb::mutex & maskStorageMutex,
+ std::mutex & maskStorageMutex,
std::unique_ptr<std::runtime_error> & error,
- tbb::mutex & errorMutex) : hashFunction(hashFunction), vertexLength(vertexLength), taskQueue(taskQueue), occurenceSet(occurenceSet),
+ std::mutex & errorMutex) : hashFunction(hashFunction), vertexLength(vertexLength), taskQueue(taskQueue), occurenceSet(occurenceSet),
mutex(mutex), tmpDirectory(tmpDirectory), round(round), maskStorage(maskStorage), maskStorageMutex(maskStorageMutex), error(error), errorMutex(errorMutex)
{
@@ -812,13 +809,13 @@ namespace TwoPaCo
size_t vertexLength;
TaskQueue & taskQueue;
OccurenceSet & occurenceSet;
- tbb::spin_rw_mutex & mutex;
+ oneapi::tbb::spin_rw_mutex & mutex;
const std::string & tmpDirectory;
size_t round;
std::ifstream & maskStorage;
- tbb::mutex & maskStorageMutex;
+ std::mutex & maskStorageMutex;
std::unique_ptr<std::runtime_error> & error;
- tbb::mutex & errorMutex;
+ std::mutex & errorMutex;
};
struct EdgeResult
@@ -856,12 +853,12 @@ namespace TwoPaCo
std::atomic<uint64_t> & currentPiece,
std::atomic<uint64_t> & occurences,
uint64_t & currentStubVertexId,
- tbb::mutex & currentStubVertexMutex,
+ std::mutex & currentStubVertexMutex,
const std::string & tmpDirectory,
std::vector<std::ifstream*> & inMaskStorage,
- tbb::mutex & inMaskStorageMutex,
+ std::mutex & inMaskStorageMutex,
std::unique_ptr<std::runtime_error> & error,
- tbb::mutex & errorMutex) : vertexLength(vertexLength), taskQueue(taskQueue), bifStorage(bifStorage),
+ std::mutex & errorMutex) : vertexLength(vertexLength), taskQueue(taskQueue), bifStorage(bifStorage),
writer(writer), currentPiece(currentPiece), occurences(occurences), tmpDirectory(tmpDirectory),
error(error), errorMutex(errorMutex), currentStubVertexId(currentStubVertexId), currentStubVertexMutex(currentStubVertexMutex),
inMaskStorage(inMaskStorage), inMaskStorageMutex(inMaskStorageMutex)
@@ -979,10 +976,10 @@ namespace TwoPaCo
std::atomic<uint64_t> & occurences;
const std::string & tmpDirectory;
std::unique_ptr<std::runtime_error> & error;
- tbb::mutex & inMaskStorageMutex;
+ std::mutex & inMaskStorageMutex;
std::vector<std::ifstream*> & inMaskStorage;
- tbb::mutex & errorMutex;
- tbb::mutex & currentStubVertexMutex;
+ std::mutex & errorMutex;
+ std::mutex & currentStubVertexMutex;
};
class FilterFillerWorker
@@ -1102,7 +1099,7 @@ namespace TwoPaCo
size_t overlapSize,
std::vector<TaskQueuePtr> & taskQueue,
std::unique_ptr<std::runtime_error> & error,
- tbb::mutex & errorMutex,
+ std::mutex & errorMutex,
std::ostream & logFile,
std::vector<size_t> & offset,
bool offsetFill)
=====================================
src/graphdump/CMakeLists.txt
=====================================
@@ -1,17 +1,14 @@
project(graphdump CXX)
-cmake_minimum_required(VERSION 2.8)
set(CMAKE_PROJECT_NAME graphdump)
-if(CMAKE_COMPILER_IS_GNUCXX)
- list(APPEND "CMAKE_CXX_FLAGS" "-std=c++11 -lstdc++")
-endif()
+set(CMAKE_CXX_STANDARD 14)
add_executable(graphdump graphdump.cpp ../common/dnachar.cpp ../common/streamfastaparser.cpp)
link_directories(${TBB_LIB_DIR})
include_directories(${twopaco_SOURCE_DIR} ${TBB_INCLUDE_DIR} "../common")
-target_link_libraries(graphdump "tbb")
+target_link_libraries(graphdump "tbb" "pthread")
install(TARGETS graphdump RUNTIME DESTINATION bin)
-set(CPACK_PACKAGE_VERSION_MAJOR "0")
-set(CPACK_PACKAGE_VERSION_MINOR "9")
-set(CPACK_PACKAGE_VERSION_PATCH "4")
+set(CPACK_PACKAGE_VERSION_MAJOR "1")
+set(CPACK_PACKAGE_VERSION_MINOR "0")
+set(CPACK_PACKAGE_VERSION_PATCH "0")
=====================================
src/graphdump/graphdump.cpp
=====================================
@@ -9,9 +9,10 @@
#include <iterator>
#include <iostream>
#include <algorithm>
+#include <unordered_map>
#include <tclap/CmdLine.h>
-#include <tbb/parallel_sort.h>
+#include "oneapi/tbb/parallel_sort.h"
#include <dnachar.h>
#include <streamfastaparser.h>
View it on GitLab: https://salsa.debian.org/med-team/twopaco/-/commit/58de084d45123a085db618661408a0cae1e17fac
--
View it on GitLab: https://salsa.debian.org/med-team/twopaco/-/commit/58de084d45123a085db618661408a0cae1e17fac
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20220929/f66f4aaa/attachment-0001.htm>
More information about the debian-med-commit
mailing list