[med-svn] [aghermann] 02/60: use log-facility in places (part 1/2)
andrei zavada
hmmr-guest at alioth.debian.org
Mon Nov 4 23:49:50 UTC 2013
This is an automated email from the git hooks/post-receive script.
hmmr-guest pushed a commit to branch WIP
in repository aghermann.
commit ebd6fb3e8510e5d4666359ebaf7ad3270517dc1a
Author: Andrei Zavada <johnhommer at gmail.com>
Date: Sun Sep 29 02:36:02 2013 +0300
use log-facility in places (part 1/2)
---
upstream/src/aghermann/expdesign/expdesign.cc | 7 ++-
upstream/src/aghermann/expdesign/recording.cc | 33 +++++++-------
upstream/src/aghermann/expdesign/subject.cc | 5 ++-
upstream/src/aghermann/expdesign/tree-scanner.cc | 33 +++++++-------
upstream/src/aghermann/model/achermann-siman.cc | 2 +-
upstream/src/aghermann/model/achermann.cc | 5 +--
upstream/src/aghermann/model/borbely.cc | 26 +++++------
upstream/src/aghermann/ui/mw/populate.cc | 52 +++++++++++++---------
8 files changed, 87 insertions(+), 76 deletions(-)
diff --git a/upstream/src/aghermann/expdesign/expdesign.cc b/upstream/src/aghermann/expdesign/expdesign.cc
index 4a3779d..a7b6c3c 100644
--- a/upstream/src/aghermann/expdesign/expdesign.cc
+++ b/upstream/src/aghermann/expdesign/expdesign.cc
@@ -90,7 +90,7 @@ CExpDesign (const string& session_dir_,
throw invalid_argument (string ("Failed to canonicalize dir: ") + session_dir_);
if ( session_dir_ != tmp ) {
- printf( "CExpDesign::CExpDesign(): canonicalized session_dir \"%s\" to \"%s\"\n", session_dir_.c_str(), tmp);
+ LOG_INFO( "canonicalized session_dir \"%s\" to \"%s\"", session_dir_.c_str(), tmp);
_session_dir.assign( tmp);
} else
_session_dir = session_dir_;
@@ -112,10 +112,10 @@ CExpDesign (const string& session_dir_,
#ifdef _OPENMP
omp_set_num_threads( (num_threads == 0) ? global::num_procs : num_threads);
- printf( "SMP enabled with %d threads\n", omp_get_max_threads());
+ LOG_INFO( "SMP enabled with %d threads", omp_get_max_threads());
#endif
if ( last_used_version != VERSION ) {
- printf( "Purging old files as we are upgrading from version %s to %s\n", last_used_version.c_str(), VERSION);
+ LOG_INFO( "Purging old files as we are upgrading from version %s to %s", last_used_version.c_str(), VERSION);
}
// last_used_version = VERSION;
/// leave it so SExpDesignUI::populate will see it and pop the changelog
@@ -141,7 +141,6 @@ log_message( const char* fmt, ...)
: (strncmp( buf, "//", 2) == 0)
? ((buf += 2), TLogEntryStyle::italic)
: TLogEntryStyle::plain;
- fprintf( stdout, "%s\n", buf0);
_error_log.emplace_back( buf, style);
}
if ( np != -1 )
diff --git a/upstream/src/aghermann/expdesign/recording.cc b/upstream/src/aghermann/expdesign/recording.cc
index ac36ac3..d0345dc 100644
--- a/upstream/src/aghermann/expdesign/recording.cc
+++ b/upstream/src/aghermann/expdesign/recording.cc
@@ -12,6 +12,7 @@
#include <list>
#include <valarray>
+#include "aghermann/globals.hh"
#include "aghermann/model/beersma.hh"
#include "recording.hh"
@@ -123,13 +124,13 @@ CProfile (CSubject& J, const string& d, const sigfile::SChannel& h,
pz = pa + M.hypnogram().n_pages();
// anchor zero page, get pagesize from edf^W CBinnedPower^W either goes
time_t dima = F.start_time();
- printf( "CProfile::CProfile(): adding %s of [%s, %s, %s] %zu pages (%zu full, %zu in hypnogram) recorded %s",
+ LOG_INFO ("adding %s of [%s, %s, %s] %zu pages (%zu full, %zu in hypnogram) recorded %s",
metrics::name(params.metric), F.subject().id.c_str(), F.session(), F.episode(),
M.total_pages(), M.full_pages(), M.hypnogram().n_pages(), ctime( &dima));
if ( pz - pa != (int)M.full_pages() ) {
- fprintf( stderr, "CProfile::CProfile(): correcting end page to match full page count in EDF: %d->%zu\n",
- pz, pa + M.full_pages());
+ LOG_WARN ("correcting end page to match full page count in EDF: %d->%zu",
+ pz, pa + M.full_pages());
pz = pa + M.full_pages();
}
_pages_in_bed += (pz-pa);
@@ -151,12 +152,12 @@ CProfile (CSubject& J, const string& d, const sigfile::SChannel& h,
create_timeline();
if ( _sim_start != (size_t)-1 )
- printf( "CProfile::CProfile(): sim start-end: %zu-%zu; avg SWA = %.4g (over %zu pp, or %.3g%% of all time in bed); "
- " SWA_L = %g; SWA[%zu] = %g\n",
- _sim_start, _sim_end, _SWA_100, _pages_with_SWA, (double)_pages_with_SWA / _pages_in_bed * 100,
- _SWA_L, _sim_start, _SWA_0);
+ LOG_INFO ("sim start-end: %zu-%zu; avg SWA = %.4g (over %zu pp, or %.3g%% of all time in bed); "
+ " SWA_L = %g; SWA[%zu] = %g",
+ _sim_start, _sim_end, _SWA_100, _pages_with_SWA, (double)_pages_with_SWA / _pages_in_bed * 100,
+ _SWA_L, _sim_start, _SWA_0);
else
- printf( "CProfile::CProfile(): status %xd, %s\n", _status, CProfile::explain_status( _status).c_str());
+ LOG_WARN ("status %xd, %s", _status, CProfile::explain_status( _status).c_str());
}
@@ -178,13 +179,13 @@ CProfile (CRecording& M,
int pa = (size_t)difftime( M.F().start_time(), _0at) / _pagesize,
pz = (size_t)difftime( M.F().end_time(), _0at) / _pagesize;
time_t dima = M.F().start_time();
- printf( "CProfile::CProfile(): adding single recording %s of [%s, %s, %s] %zu pages (%zu full, %zu in hypnogram) recorded %s",
+ LOG_INFO ("adding single recording %s of [%s, %s, %s] %zu pages (%zu full, %zu in hypnogram) recorded %s",
metrics::name(params.metric), M.F().subject().id.c_str(), M.F().session(), M.F().episode(),
M.total_pages(), M.full_pages(), M.hypnogram().n_pages(), ctime( &dima));
if ( pz - pa != (int)M.full_pages() ) {
- fprintf( stderr, "CProfile::CProfile(): correcting end page to match full page count in EDF: %d->%zu\n",
- pz, pa + M.full_pages());
+ LOG_WARN ("correcting end page to match full page count in EDF: %d->%zu",
+ pz, pa + M.full_pages());
pz = pa + M.full_pages();
}
_pages_in_bed += (pz-pa);
@@ -205,12 +206,12 @@ CProfile (CRecording& M,
create_timeline();
if ( _sim_start != (size_t)-1 )
- printf( "CProfile::CProfile(): sim start-end: %zu-%zu; avg SWA = %.4g (over %zu pp, or %.3g%% of all time in bed); "
- " SWA_L = %g; SWA[%zu] = %g\n",
- _sim_start, _sim_end, _SWA_100, _pages_with_SWA, (double)_pages_with_SWA / _pages_in_bed * 100,
- _SWA_L, _sim_start, _SWA_0);
+ LOG_INFO ("CProfile::CProfile(): sim start-end: %zu-%zu; avg SWA = %.4g (over %zu pp, or %.3g%% of all time in bed); "
+ " SWA_L = %g; SWA[%zu] = %g",
+ _sim_start, _sim_end, _SWA_100, _pages_with_SWA, (double)_pages_with_SWA / _pages_in_bed * 100,
+ _SWA_L, _sim_start, _SWA_0);
else
- printf( "CProfile::CProfile(): status %xd, %s\n", _status, CProfile::explain_status( _status).c_str());
+ LOG_WARN ("status %xd, %s", _status, CProfile::explain_status( _status).c_str());
}
diff --git a/upstream/src/aghermann/expdesign/subject.cc b/upstream/src/aghermann/expdesign/subject.cc
index 9046950..962ffdb 100644
--- a/upstream/src/aghermann/expdesign/subject.cc
+++ b/upstream/src/aghermann/expdesign/subject.cc
@@ -11,6 +11,7 @@
#include "common/containers.hh"
+#include "aghermann/globals.hh"
#include "aghermann/model/achermann.hh"
#include "recording.hh"
#include "subject.hh"
@@ -69,8 +70,8 @@ SEpisode (sigfile::CTypedSource&& F_,
sources.emplace_back( move(F_));
auto& F = sources.back();
auto HH = F().channel_list();
- printf( "SEpisode::SEpisode( \"%s\"): %s\n",
- F().filename(), sigfile::join_channel_names(HH, ", ").c_str());
+ LOG_INFO ("SEpisode( \"%s\"): %s",
+ F().filename(), sigfile::join_channel_names(HH, ", ").c_str());
int h = 0;
for ( auto& H : HH )
recordings.insert( {H, {F, h++, fft_params, swu_params, mc_params}});
diff --git a/upstream/src/aghermann/expdesign/tree-scanner.cc b/upstream/src/aghermann/expdesign/tree-scanner.cc
index 844d3fd..f42879e 100644
--- a/upstream/src/aghermann/expdesign/tree-scanner.cc
+++ b/upstream/src/aghermann/expdesign/tree-scanner.cc
@@ -15,20 +15,20 @@
#include <string>
#include "common/alg.hh"
+#include "aghermann/globals.hh"
#include "common/containers.hh"
#include "libsigfile/all.hh"
#include "expdesign.hh"
using namespace std;
-
using namespace agh;
namespace {
struct progress_fun_stdout_fo {
void operator()( const string& current, size_t n, size_t i) const
{
- printf( "(%zu of %zu) %s\n", i, n, current.c_str());
+ LOG_INFO ("(%zu of %zu) %s\n", i, n, current.c_str());
}
};
} // namespace
@@ -73,8 +73,8 @@ add_one( sigfile::CTypedSource&& Fmc,
} else { // same as SEpisode() but done on an existing one
// check that the edf source being added has exactly the same timestamp and duration
- printf( "SEpisodeSequence::add_one( \"%s\") try in-place\n",
- Fmc().filename());
+ LOG_INFO( "SEpisodeSequence::add_one( \"%s\") try in-place\n",
+ Fmc().filename());
if ( fabs( difftime( Ei->start_time(), Fmc().start_time())) > 1 )
return AGH_EPSEQADD_TOOFAR;
Ei->sources.emplace_back( move(Fmc));
@@ -210,24 +210,24 @@ register_intree_source( sigfile::CTypedSource&& F,
// F().subject().id.c_str(), F().subject().name.c_str(), F().subject().gender_sign(), ctime(&F().subject().dob));
if ( J->try_update_subject_details( F().subject()) ) {
if ( strict_subject_id_checks ) {
- fprintf( stderr, "%s: subject details mismatch", F().filename());
+ LOG_WARN( "%s: subject details mismatch", F().filename());
return -1;
} else
- fprintf( stderr, "%s: keeping previously recorded subject details", F().filename());
+ LOG_WARN( "%s: keeping previously recorded subject details", F().filename());
}
// insert/update episode observing start/end times
- printf( "\nCExpDesign::register_intree_source( file: \"%s\", J: %s (\"%s\"), E: \"%s\", D: \"%s\")\n",
+ LOG_INFO( "register_intree_source( file: \"%s\", J: %s (\"%s\"), E: \"%s\", D: \"%s\")",
F().filename(), F().subject().id.c_str(), F().subject().name.c_str(), F().episode(), F().session());
switch ( J->measurements[F().session()].add_one(
move(F), fft_params, swu_params, mc_params) ) { // this will do it
case AGH_EPSEQADD_OVERLAP:
- log_message( "%s: not added as it overlaps with existing episodes",
- F().filename());
+ log_message( "%s: not added as it overlaps with existing episodes", F().filename());
+ LOG_WARN( "%s: not added as it overlaps with existing episodes", F().filename());
return -1;
case AGH_EPSEQADD_TOOFAR:
- log_message( "%s: not added as it is too far removed from the rest",
- F().filename());
+ log_message( "%s: not added as it is too far removed from the rest", F().filename());
+ LOG_WARN ( "%s: not added as it is too far removed from the rest", F().filename());
return -1;
default:
return 0;
@@ -240,6 +240,7 @@ register_intree_source( sigfile::CTypedSource&& F,
return -1;
} catch (int status) {
log_message( "Bad edf header or data");
+ LOG_WARN( "Bad edf header or data");
if ( reason_if_failed_p )
*reason_if_failed_p = "Bad edf header or data";
return -1;
@@ -326,7 +327,7 @@ scan_tree( TMsmtCollectProgressIndicatorFun user_progress_fun)
// glob it!
fs::total_supported_sigfiles = 0;
nftw( "./", fs::supported_sigfile_counter, 20, 0);
- printf( "CExpDesign::scan_tree(\"%s\"): %zu edf file(s) found\n",
+ LOG_INFO( "scan_tree(\"%s\"): %zu edf file(s) found",
session_dir(), fs::total_supported_sigfiles);
if ( fs::total_supported_sigfiles == 0 )
return;
@@ -335,10 +336,10 @@ scan_tree( TMsmtCollectProgressIndicatorFun user_progress_fun)
only_progress_fun = user_progress_fun;
only_expdesign = this;
nftw( "./", supported_sigfile_processor, 10, 0);
- printf( "CExpDesign::scan_tree(): recordings collected\n");
+ LOG_INFO( "scan_tree(): recordings collected");
compute_profiles(); // in an SMP fashion
- printf( "CExpDesign::scan_tree(): all computed\n");
+ LOG_INFO( "scan_tree(): all computed");
// find any subjects with incomplete episode sets
list<string> complete_episode_set = enumerate_episodes();
@@ -350,8 +351,8 @@ scan_tree( TMsmtCollectProgressIndicatorFun user_progress_fun)
for ( auto &D : J.measurements )
if ( D.second.episodes.size() < n_episodes &&
complete_episode_set.front() != D.second.episodes.begin()->name() ) { // the baseline is missing
- log_message( "No Baseline episode in %s's %s: skip this session",
- J.id.c_str(), D.first.c_str());
+ log_message( "No Baseline episode in %s's %s: skip this session", J.id.c_str(), D.first.c_str());
+ LOG_WARN( "No Baseline episode in %s's %s: skip this session", J.id.c_str(), D.first.c_str());
J.measurements.erase(D.first);
goto startover;
}
diff --git a/upstream/src/aghermann/model/achermann-siman.cc b/upstream/src/aghermann/model/achermann-siman.cc
index aed73c8..c2a86dd 100644
--- a/upstream/src/aghermann/model/achermann-siman.cc
+++ b/upstream/src/aghermann/model/achermann-siman.cc
@@ -113,7 +113,7 @@ _siman_metric( void *xp, void *yp)
memcpy( X1.P, P1.t, sizeof(double) * X1.size());
memcpy( X2.P, P2.t, sizeof(double) * X2.size());
- printf( "metric %g\n", agh::ach::distance( X1, X2, P1.R->tstep.P));
+ //printf( "metric %g\n", agh::ach::distance( X1, X2, P1.R->tstep.P));
return agh::ach::distance( X1, X2, P1.R->tstep.P);
}
diff --git a/upstream/src/aghermann/model/achermann.cc b/upstream/src/aghermann/model/achermann.cc
index c829430..ada28ac 100644
--- a/upstream/src/aghermann/model/achermann.cc
+++ b/upstream/src/aghermann/model/achermann.cc
@@ -125,13 +125,13 @@ _prepare_scores2()
if ( ctl_params.ScoreUnscoredAsWake ) {
for ( p = _sim_start; p < _timeline.size(); ++p )
if ( _scores2[p].NREM + _scores2[p].REM + _scores2[p].Wake == 0 ) { // this is Unscored
-// printf( " (patching Unscored as Wake at %d)\n", p);
+ //LOG_DEBUG ("patching Unscored as Wake at %d", p);
_scores2[p].Wake = 1.;
}
} else { // ... as prev page
for ( p = (_sim_start > 0) ?_sim_start :1; p < _timeline.size(); ++p )
if ( _scores2[p].NREM + _scores2[p].REM + _scores2[p].Wake == 0 ) {
-// printf( " (patching Unscored as prev at %d)\n", p);
+ //LOG_DEBUG ("patching Unscored as prev at %d", p);
pp = p-1;
do
_scores2[p] = _scores2[pp];
@@ -195,7 +195,6 @@ __attribute__ ((hot))
agh::ach::CModelRun::
snapshot()
{
-// printf( "AZAmendment = %d; cur_tset.size = %zu\n", AZAmendment, cur_tset.size());
const float ppm = 60. / pagesize();
auto _tset = tx;
_tset.adjust_for_ppm( ppm);
diff --git a/upstream/src/aghermann/model/borbely.cc b/upstream/src/aghermann/model/borbely.cc
index 480c00c..4e281f3 100644
--- a/upstream/src/aghermann/model/borbely.cc
+++ b/upstream/src/aghermann/model/borbely.cc
@@ -17,6 +17,7 @@
#include "common/alg.hh"
#include "libmetrics/psd.hh"
#include "libmetrics/mc.hh"
+#include "aghermann/globals.hh"
#include "aghermann/expdesign/recording.hh"
#include "beersma.hh"
@@ -88,12 +89,12 @@ expb_fdf( const gsl_vector* x, void *data,
void
print_state( size_t iter, gsl_multifit_fdfsolver* s)
{
- printf ("iter: %3zu x = % 15.8f "
- "|f(x)| = %g\n",
- iter,
- gsl_vector_get (s->x, 0),
+ LOG_DEBUG ("iter: %3zu x = % 15.8f "
+ "|f(x)| = %g",
+ iter,
+ gsl_vector_get (s->x, 0),
// gsl_vector_get (s->x, 1),
- gsl_blas_dnrm2 (s->f));
+ gsl_blas_dnrm2 (s->f));
}
} // namespace
@@ -104,13 +105,13 @@ classic_fit( agh::CRecording& M,
const agh::beersma::SClassicFitCtl& P)
{
// set up
- auto course = agh::alg::to_vad( M.course( P.P));
- auto pp = course.size(),
+ auto course = agh::alg::to_vad( M.course( P.P));
+ auto pp = course.size(),
pagesize = M.pagesize();
// determine A (SWA_0) and b (SWA_L)
- double SWA_0, SWA_L;
+ double SWA_0, SWA_L;
{
// this one doesn't throw
agh::CProfile tmp (M, P.P);
@@ -165,7 +166,7 @@ classic_fit( agh::CRecording& M,
print_state( iter, S);
if ( status ) {
- printf ("status = %s\n", gsl_strerror( status));
+ LOG_WARN ("status = %s", gsl_strerror( status));
break;
}
@@ -182,12 +183,11 @@ classic_fit( agh::CRecording& M,
double dof = pp - 1;
double c = GSL_MAX_DBL(1, chi / sqrt(dof));
- printf("chisq/dof = %g\n", gsl_pow_2(chi) / dof);
-
- printf ("r = %.5f +/- %.5f\n\n", FIT(0), c*ERR(0));
+ LOG_DEBUG ("chisq/dof = %g", gsl_pow_2(chi) / dof);
+ LOG_DEBUG ("r = %.5f +/- %.5f", FIT(0), c*ERR(0));
}
- double rate = gsl_vector_get( S->x, 0);
+ double rate = gsl_vector_get( S->x, 0);
gsl_multifit_fdfsolver_free( S);
gsl_matrix_free( covar);
diff --git a/upstream/src/aghermann/ui/mw/populate.cc b/upstream/src/aghermann/ui/mw/populate.cc
index 6f111f8..e382543 100644
--- a/upstream/src/aghermann/ui/mw/populate.cc
+++ b/upstream/src/aghermann/ui/mw/populate.cc
@@ -9,10 +9,10 @@
* License: GPL
*/
-
#include <cstring>
#include <sstream>
+#include "aghermann/globals.hh"
#include "aghermann/expdesign/expdesign.hh"
#include "aghermann/model/beersma.hh"
#include "aghermann/ui/misc.hh"
@@ -27,7 +27,7 @@ int
SExpDesignUI::
populate( bool do_load)
{
- printf( "\nSExpDesignUI::populate():\n");
+ LOG_INFO ("SExpDesignUI::populate():");
AghDD = ED->enumerate_sessions();
_AghDi = AghDD.begin();
AghGG = ED->enumerate_groups();
@@ -39,29 +39,31 @@ populate( bool do_load)
AghEE = ED->enumerate_episodes();
_AghEi = AghEE.begin();
- printf( "* Sessions: %s\n"
- "* Groups: %s\n"
- "* All Channels: %s\n"
- "* EEG Channels: %s\n"
- "* Episodes: %s\n",
- agh::str::join( AghDD, "; ").c_str(),
- agh::str::join( AghGG, "; ").c_str(),
- sigfile::join_channel_names( AghHH, "; ").c_str(),
- sigfile::join_channel_names( AghTT, "; ").c_str(),
- agh::str::join( AghEE, "; ").c_str());
+ LOG_INFO ("* Sessions: %s\n"
+ "* Groups: %s\n"
+ "* All Channels: %s\n"
+ "* EEG Channels: %s\n"
+ "* Episodes: %s",
+ agh::str::join( AghDD, "; ").c_str(),
+ agh::str::join( AghGG, "; ").c_str(),
+ sigfile::join_channel_names( AghHH, "; ").c_str(),
+ sigfile::join_channel_names( AghTT, "; ").c_str(),
+ agh::str::join( AghEE, "; ").c_str());
used_samplerates =
ED->used_samplerates();
used_eeg_samplerates =
ED->used_samplerates( sigfile::SChannel::TType::eeg);
if ( used_eeg_samplerates.size() == 1 )
- printf( "* single common EEG samplerate: %zu\n", used_eeg_samplerates.front());
+ LOG_INFO ("single common EEG samplerate: %zu", used_eeg_samplerates.front());
else
- printf( "* multiple EEG samplerates (%zu)\n", used_eeg_samplerates.size());
+ LOG_INFO ("multiple EEG samplerates (%zu)", used_eeg_samplerates.size());
if ( do_load ) {
- if ( load_settings() )
- fprintf( stderr, "load_settings() had issues\n");
+ if ( load_settings() ) {
+ LOG_WARN ("load_settings() had issues");
+ pop_ok_message( wMainWindow, "Settings could not be loaded", "It's ok, we'll use the defaults.");
+ }
if ( geometry.w > 0 ) {// implies the rest are, too
// gtk_window_parse_geometry( wMainWindow, _geometry_placeholder.c_str());
gtk_window_move( wMainWindow, geometry.x, geometry.y);
@@ -74,7 +76,7 @@ populate( bool do_load)
(string ("Aghermann: ") + agh::str::homedir2tilda( ED->session_dir())).c_str());
if ( ED->last_used_version != VERSION ) {
- printf( "Upgrading from version %s, here's ChangeLog for you\n", ED->last_used_version.c_str());
+ LOG_INFO ("Upgrading from version %s, here's ChangeLog for you", ED->last_used_version.c_str());
show_changelog();
}
ED->last_used_version = VERSION;
@@ -405,7 +407,7 @@ populate_1()
(GtkCallback)gtk_widget_destroy,
NULL);
- printf( "SExpDesignUI::populate_1(): session \"%s\", channel \"%s\"\n", AghD(), AghT());
+ LOG_INFO ("populate_1(): session \"%s\", channel \"%s\"", AghD(), AghT());
time_t earliest_start = (time_t)-1,
latest_end = (time_t)-1;
@@ -442,9 +444,17 @@ populate_1()
tl_width = (timeline_end - timeline_start) / 3600 * tl_pph;
tl_pages = (timeline_end - timeline_start) / ED->fft_params.pagesize;
- printf( "SExpDesignUI::populate_1(): common timeline:\n");
- fputs( asctime( localtime(&earliest_start)), stdout);
- fputs( asctime( localtime(&latest_end)), stdout);
+ LOG_INFO ("populate_1(): common timeline:");
+ {
+ string t {asctime( localtime(&earliest_start))};
+ t.pop_back();
+ LOG_INFO (t.c_str());
+ }
+ {
+ string t {asctime( localtime(&latest_end))};
+ t.pop_back();
+ LOG_INFO (t.c_str());
+ }
tl_left_margin = tl_right_margin = 0;
--
Alioth's /git/debian-med/git-commit-notice on /srv/git.debian.org/git/debian-med/aghermann.git
More information about the debian-med-commit
mailing list