aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2019-08-09 14:57:12 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2019-08-09 15:37:45 +0300
commit1f44107ca2267fadd64c5a7070fa493b7b4c1d53 (patch)
treec7ef41bd6f981e79addb139fcd66418ee995c200
parentfe48e311bd39fd429e5debf490f790557a9ef371 (diff)
downloadvcsync-1f44107ca2267fadd64c5a7070fa493b7b4c1d53.tar.gz
vcsync-1f44107ca2267fadd64c5a7070fa493b7b4c1d53.tar.bz2
Implement automatic detection of the VCS used.
If vcsync binary is symlinked to the hooks subdirectory of a git or svn repository, it will detect the fact and will assume the corresponding VCS flavor (unless explicitly told otherwise). In this case the first named configuration that has the matching VCS type will be used. * src/config.c (cb_vcs_type): Set both vcs_type and proc. (cb_config): Build a singly-linked list of configurations. (vcsync_config_kw,vcsync_kw): Pass a pointer to struct vcsync_config. (config_finish): If vcs_type is not set, try to detect what VCS is used. * src/diag.c (fullprogname): New global. (setprogname): Set fullprogname. * src/git.c (get_cwd): Move to vcsync.c * src/vcsync.c (parsefilename,string_suffix) (get_cwd,guess_vcs_type): New functions. * src/vcsync.h (fullprogname): New extern. (vcs_type): Remove const qualifier. (parsefilename,string_suffix) (get_cwd,guess_vcs_type,vdiag): New protos. * src/checkoutrc.c: Shut up gcc warning. * src/runcmd.c: Likewise. * src/svn.c: Likewise. * tests/checkoutrc-rec.at: Account for additional debug message. * tests/checkoutrc.at: Likewise. * tests/cvscom00.at: Account for eventual debug messages. * tests/cvscom01.at: Likewise. * tests/cvscom02.at: Likewise. * tests/cvscom03.at: Likewise. * tests/cvscom04.at: Likewise. * tests/cvsimp.at: Likewise. * tests/cvsimp01.at: Likewise. * tests/gitimp.at: Likewise. * tests/gitimp01.at: Likewise. * tests/gitpush00.at: Likewise. * tests/gitpush01.at: Likewise. * tests/gitpush02.at: Likewise. * tests/gitpush03.at: Likewise. * tests/namedconf00.at: Likewise. * tests/svncom00.at: Likewise. * tests/svncom01.at: Likewise. * tests/svncom02.at: Likewise. * tests/svncom03.at: Likewise. * tests/svncom04.at: Likewise. * tests/svnimp.at: Likewise. * tests/svnimp01.at: Likewise.
-rw-r--r--doc/vcsync.826
-rw-r--r--src/checkoutrc.c3
-rw-r--r--src/config.c99
-rw-r--r--src/diag.c4
-rw-r--r--src/git.c37
-rw-r--r--src/runcmd.c2
-rw-r--r--src/svn.c1
-rw-r--r--src/vcsync.c241
-rw-r--r--src/vcsync.h29
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/atlocal.in3
-rw-r--r--tests/checkoutrc-rec.at5
-rw-r--r--tests/checkoutrc.at5
-rw-r--r--tests/cvscom00.at10
-rw-r--r--tests/cvscom01.at10
-rw-r--r--tests/cvscom02.at10
-rw-r--r--tests/cvscom03.at9
-rw-r--r--tests/cvscom04.at9
-rw-r--r--tests/cvsimp.at9
-rw-r--r--tests/cvsimp01.at9
-rw-r--r--tests/gitimp.at9
-rw-r--r--tests/gitimp01.at9
-rw-r--r--tests/gitpush00.at10
-rw-r--r--tests/gitpush01.at9
-rw-r--r--tests/gitpush02.at9
-rw-r--r--tests/gitpush03.at9
-rw-r--r--tests/namedconf00.at10
-rw-r--r--tests/svncom00.at10
-rw-r--r--tests/svncom01.at9
-rw-r--r--tests/svncom02.at9
-rw-r--r--tests/svncom03.at9
-rw-r--r--tests/svncom04.at9
-rw-r--r--tests/svnimp.at9
-rw-r--r--tests/svnimp01.at9
-rw-r--r--tests/testsuite.at3
35 files changed, 529 insertions, 126 deletions
diff --git a/doc/vcsync.8 b/doc/vcsync.8
index d4c9551..5d89647 100644
--- a/doc/vcsync.8
+++ b/doc/vcsync.8
@@ -13,7 +13,7 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with Vcsync. If not, see <http://www.gnu.org/licenses/>.
-.TH VCSYNC 8 "July 24, 2019" "VCSYNC"
+.TH VCSYNC 8 "August 9, 2019" "VCSYNC"
.SH NAME
vcsync \- synchronize version control system updates with the file system
.SH SYNOPSIS
@@ -146,6 +146,9 @@ destination-root /srv/home;
.EE
.RE
.PP
+The \fBvcs\-type\fR statement is optional. If missing, it will be
+detected automatically. See the section \fBVCS DETECTION\fR for details.
+.PP
The project name is deduced from the first argument, by selecting its
trailing directory component.
.SS GIT
@@ -170,6 +173,9 @@ destination-root /srv/home;
.EE
.RE
.PP
+The \fBvcs\-type\fR statement is optional. If missing, it will be
+detected automatically. See the section \fBVCS DETECTION\fR for details.
+.PP
The project name is obtained from the last directory component of the
current working directory (which is set by \fBgit\fR to the repository
being modified). The \fB.git\fR suffix will be removed.
@@ -323,7 +329,8 @@ where \fIstatements\fR is a list of statements discussed above. This
configuration takes effect (instead of the global configuration), if
\fBvcsync\fR is invoked with the \fB\-N\fR (\fB\-\-name\fR) command line
option whose argument matches the \fIname\fR in the \fBconfig\fR
-block.
+block. Named configurations are also used if the VCS type is not
+explicitly specified. See the section \fBVCS DETECTION\fR for details.
.SS Logging
The following configuration statement controls the \fBsyslog\fR output:
.sp
@@ -340,6 +347,21 @@ The following configuration statement controls the \fBsyslog\fR output:
.B }
.in
.fi
+.SH VCS DETECTION
+If the VCS type is not supplied explicitly (by the \fBvcs\-type\fR configuration
+setting or the \fB\-\-vcs\-type\fR option), the program attempts to
+determine it by looking at the name with which it is invoked. If is
+able to correctly determine the VCS type, if it is being run from the
+\fBhooks\fR subdirectory of a \fBgit\fR or \fBSVN\fR repository.
+Otherwise, it will assume the default VCS type.
+.PP
+When the VCS type is established, the program will look in the
+configuration file for the first named configuration that lists the
+detected type in its \fBvcs\-type\fR statement and will use it. If no
+such configuration is found, the default one will be used.
+.PP
+Thus, a single configuration file can be used for all three supported
+version control systems.
.SH CHECKOUTRC
A special feature is provided to use
.B vcsync
diff --git a/src/checkoutrc.c b/src/checkoutrc.c
index b22caed..07dff0d 100644
--- a/src/checkoutrc.c
+++ b/src/checkoutrc.c
@@ -699,9 +699,8 @@ flush_checkoutrc_files(const char *root_dir)
}
namebuf[preflen++] = '/';
- while (ent = readdir(d)) {
+ while ((ent = readdir(d))) {
const char *name = ent->d_name;
- size_t flen;
/* Skip "", ".", and "..". "" is returned
by at least one buggy implementation:
diff --git a/src/config.c b/src/config.c
index ac669fc..d3eeb35 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1,5 +1,5 @@
/* This file is part of Vcsync
- Copyright (C) 2014 Sergey Poznyakoff
+ Copyright (C) 2014, 2019 Sergey Poznyakoff
Vcsync is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,8 +22,9 @@ int cfg_facility = LOG_USER;
int cfg_print_priority;
char *cfg_tag;
struct vcsync_config default_config;
+static struct vcsync_config *config_head, *config_tail;
struct vcsync_config *config;
-char *config_name;
+char const *config_name;
#define ASSERT_SCALAR(cmd, locus) \
if ((cmd) != grecs_callback_set_value) { \
@@ -69,13 +70,14 @@ cb_vcs_type(enum grecs_callback_command cmd, grecs_node_t *node,
{
grecs_locus_t *locus = &node->locus;
grecs_value_t *value = node->v.value;
- vcs_proc_fn *pproc = (vcs_proc_fn *)varptr;
+ struct vcsync_config *conf = varptr;
ASSERT_SCALAR(cmd, locus);
if (assert_grecs_value_type(&value->locus, value, GRECS_TYPE_STRING))
return 1;
- *pproc = vcs_proc_get(value->v.string);
- if (!*pproc)
+ conf->vcs_type = estrdup(value->v.string);
+ conf->proc = vcs_proc_get(value->v.string);
+ if (!conf->proc)
grecs_error(locus, 0, "unknown VCS");
return 0;
}
@@ -445,7 +447,6 @@ static int
cb_config(enum grecs_callback_command cmd, grecs_node_t *node,
void *varptr, void *cb_data)
{
- int err = 0;
struct vcsync_config *cp, **pcp = cb_data;
switch (cmd) {
@@ -460,10 +461,11 @@ cb_config(enum grecs_callback_command cmd, grecs_node_t *node,
case grecs_callback_section_end:
cp = *pcp;
- if (config_name && strcmp(cp->name, config_name) == 0)
- config = cp;
+ if (config_tail)
+ config_tail->next = cp;
else
- vcsync_config_free(cp);
+ config_head = cp;
+ config_tail = cp;
break;
case grecs_callback_set_value:
@@ -479,7 +481,7 @@ static struct grecs_keyword vcsync_config_kw[] = {
NULL, offsetof(struct vcsync_config, debug_level) },
{ "vcs-type", "arg: cvs|svn|git", "Set the type of VCS to use",
grecs_type_string, GRECS_DFLT,
- NULL, offsetof(struct vcsync_config, proc), cb_vcs_type },
+ NULL, 0, cb_vcs_type },
{ "vcs-command", "command", "Set VCS command line",
grecs_type_string, GRECS_DFLT,
NULL, offsetof(struct vcsync_config, vcs_command) },
@@ -516,7 +518,7 @@ static struct grecs_keyword vcsync_kw[] = {
&default_config.debug_level },
{ "vcs-type", "arg: cvs|svn|git", "Set the type of VCS to use",
grecs_type_string, GRECS_DFLT,
- &default_config.proc, 0, cb_vcs_type },
+ &default_config, 0, cb_vcs_type },
{ "vcs-command", "command", "Set VCS command line",
grecs_type_string, GRECS_DFLT,
&default_config.vcs_command },
@@ -585,31 +587,78 @@ config_init()
grecs_print_diag_fun = vcsync_print_grecs_diag;
}
+static struct vcsync_config *
+vcsync_config_lookup_name(char const *name)
+{
+ struct vcsync_config *cp;
+
+ for (cp = config_head; cp; cp = cp->next) {
+ if (strcmp(cp->name, name) == 0)
+ break;
+ }
+ return cp;
+}
+
+static struct vcsync_config *
+vcsync_config_lookup_type(char const *type)
+{
+ struct vcsync_config *cp;
+
+ for (cp = config_head; cp; cp = cp->next) {
+ if (strcmp(cp->vcs_type, type) == 0)
+ break;
+ }
+ return cp;
+}
+
void
config_finish(struct grecs_node *tree)
-{
- if (tree && grecs_tree_process(tree, vcsync_kw))
- exit(EX_CONFIG);
- if (!config) {
- if (config_name)
+{
+ if (tree && grecs_tree_process(tree, vcsync_kw))
+ exit(EX_CONFIG);
+
+ if (config_name) {
+ config = vcsync_config_lookup_name(config_name);
+ if (!config)
die(EX_USAGE, "configuration \"%s\" not defined",
config_name);
+ } else if (default_config.vcs_type) {
+ default_config.proc = vcs_proc_get(default_config.vcs_type);
+ if (!default_config.proc)
+ die(EX_USAGE, "unknown VCS: %s",
+ default_config.vcs_type);
config = &default_config;
+ } else {
+ if (vcs_type) {
+ default_config.vcs_type = (char*)vcs_type;
+ default_config.proc = vcs_proc_get(vcs_type);
+ if (!default_config.proc)
+ die(EX_USAGE, "unknown VCS: %s", vcs_type);
+ } else {
+ if ((vcs_type = guess_vcs_type())) {
+ debug(1, ("detected VCS %s", vcs_type));
+ config = vcsync_config_lookup_type(vcs_type);
+ } else
+ vcs_type = DEFAULT_VCS;
+ if (!config) {
+ default_config.vcs_type = (char*)vcs_type;
+ default_config.proc = vcs_proc_get(vcs_type);
+ config = &default_config;
+ }
+ }
}
-
+
if (!debug_level)
debug_level = config->debug_level;
if (!cfg_tag)
cfg_tag = (char*) progname;
- if (vcs_type) {
- config->proc = vcs_proc_get(vcs_type);
- if (!config->proc)
- die(EX_USAGE, "unknown VCS: %s", vcs_type);
- } else if (!config->proc) {
- config->proc = vcs_proc_get(DEFAULT_VCS);
- assert(config->proc != NULL);
- }
+ if (!config->name)
+ debug(1, ("using default configuration for VCS %s",
+ config->vcs_type));
+ else
+ debug(1, ("using configuration \"%s\" for VCS %s",
+ config->name, config->vcs_type));
if (destination_root)
config->dest_root = destination_root;
diff --git a/src/diag.c b/src/diag.c
index 9496ac4..21a3af7 100644
--- a/src/diag.c
+++ b/src/diag.c
@@ -18,6 +18,7 @@
#include "vcsync.h"
#include "grecs/locus.h"
+const char *fullprogname;
const char *progname;
int log_to_stderr = LOG_DEBUG;
@@ -26,6 +27,7 @@ setprogname(const char *arg)
{
char *p;
+ fullprogname = arg;
p = strrchr(arg, '/');
if (p)
progname = p + 1;
@@ -121,7 +123,7 @@ vdiag(int prio, const char *fmt, va_list ap)
*p++ = *s++;
*p++ = ']';
*p++ = ' ';
- while (*p++ = *fmt++);
+ while ((*p++ = *fmt++));
vsyslog(prio, fmtbuf, ap);
} else
vsyslog(prio, fmt, ap);
diff --git a/src/git.c b/src/git.c
index 06e7a0c..6e5f4b8 100644
--- a/src/git.c
+++ b/src/git.c
@@ -22,7 +22,6 @@
#define MASTER_REF_STR "refs/heads/master"
#define MASTER_REF_LEN (sizeof(MASTER_REF_STR)-1)
-static char *get_cwd(void);
static void receive(const char *directory, const char *git_dir,
const char *oldrev, const char *newrev, int clone);
@@ -122,40 +121,6 @@ git_proc(int argc, char **argv)
return clone ? NULL : directory;
}
-static char *
-get_cwd(void)
-{
- char *ret;
- unsigned path_max;
- char buf[128];
-
- errno = 0;
- ret = getcwd(buf, sizeof(buf));
- if (ret != NULL)
- return estrdup(buf);
-
- if (errno != ERANGE)
- die(EX_FAIL, "can't get cwd: %s", strerror(errno));
-
- path_max = 128;
- path_max += 2; /* The getcwd docs say to do this. */
-
- for (;;) {
- char *cwd = emalloc(path_max);
- errno = 0;
- ret = getcwd(cwd, path_max);
- if (ret)
- break;
- if (errno != ERANGE)
- die(EX_FAIL, "can't get cwd: %s", strerror(errno));
- free(cwd);
-
- path_max += path_max / 16;
- path_max += 32;
- }
- return ret;
-}
-
static void
receive(const char *directory, const char *git_dir,
const char *oldrev, const char *newrev, int clone)
@@ -179,8 +144,6 @@ receive(const char *directory, const char *git_dir,
} else {
int fd;
FILE *fp;
- size_t i, xargc, xargalloc;
- char **xargv;
char *inbuf = NULL;
size_t insize = 0;
diff --git a/src/runcmd.c b/src/runcmd.c
index 2449822..c144c2e 100644
--- a/src/runcmd.c
+++ b/src/runcmd.c
@@ -195,8 +195,6 @@ runcmd(char **argv, int *pfd)
if (debug_level >= 1) {
int i;
struct grecs_txtacc *acc = grecs_txtacc_create();
- char *locstr = NULL;
- size_t locsize = 0;
grecs_txtacc_grow_string(acc, argv[0]);
for (i = 1; argv[i]; i++) {
diff --git a/src/svn.c b/src/svn.c
index a660e89..9c8d644 100644
--- a/src/svn.c
+++ b/src/svn.c
@@ -17,6 +17,7 @@
#include "vcsync.h"
#include "wordsplit.h"
#include <sys/stat.h>
+#include <unistd.h>
/* To use SVN mode, add the following to your post-commit hook:
diff --git a/src/vcsync.c b/src/vcsync.c
index 8e52e59..efb315f 100644
--- a/src/vcsync.c
+++ b/src/vcsync.c
@@ -1,5 +1,5 @@
/* This file is part of Vcsync
- Copyright (C) 2014 Sergey Poznyakoff
+ Copyright (C) 2014, 2019 Sergey Poznyakoff
Vcsync is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,7 +15,11 @@
along with Vcsync. If not, see <http://www.gnu.org/licenses/>.
*/
#include "vcsync.h"
+#include <unistd.h>
#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
int dry_run;
int debug_level;
@@ -25,7 +29,7 @@ char *config_file;
char *destination_root;
unsigned sleep_option;
int detach_option;
-char *vcs_type;
+char const *vcs_type;
struct vcs_tab {
const char *name;
@@ -64,7 +68,7 @@ pathcat(const char **path)
ret = emalloc(len + 1);
for (pp = path, p = ret; *pp; pp++) {
- for (q = *pp; *p = *q; p++, q++)
+ for (q = *pp; (*p = *q); p++, q++)
;
if (pp[1])
*p++ = '/';
@@ -85,6 +89,233 @@ mkfilename(const char *dir, const char *name)
return pathcat(a);
}
+char *
+parsefilename(const char *fname, char **basename)
+{
+ char *retval;
+ size_t len;
+
+ len = strlen (fname);
+ while (len > 0 && fname[len-1] == '/')
+ --len;
+
+ if (len == 0) {
+ retval = emalloc(2);
+ retval[0] = '/';
+ retval[1] = 0;
+
+ if (basename)
+ *basename = NULL;
+ } else {
+ size_t i;
+
+ for (i = len - 1; i > 0 && fname[i-1] != '/'; i--)
+ ;
+
+ if (i) {
+ if (basename) {
+ size_t baselen = len - i;
+ *basename = emalloc(baselen + 1);
+ memcpy(*basename, fname + i, baselen);
+ (*basename)[baselen] = 0;
+ }
+
+ while (i > 0 && fname[i-1] == '/')
+ i--;
+
+ retval = emalloc(i + 1);
+ memcpy(retval, fname, i);
+ retval[i] = 0;
+ } else {
+ if (basename)
+ *basename = estrdup(fname);
+ retval = estrdup(".");
+ }
+ }
+
+ if (strcmp(retval, ".") == 0) {
+ free(retval);
+ retval = get_cwd();
+ } else if (strncmp(retval, "./", 2) == 0 || retval[0] != '/') {
+ char *p = mkfilename(get_cwd(),
+ retval + (retval[0] == '.' ? 2 : 0));
+ free(retval);
+ retval = p;
+ }
+ return retval;
+}
+
+int
+string_suffix(char const *str, char const *suf)
+{
+ char const *estr;
+ char const *esuf;
+
+ if (!str || !suf)
+ return 0;
+
+ estr = str + strlen (str) - 1;
+ esuf = suf + strlen (suf) - 1;
+ while (estr >= str && *estr == *esuf) {
+ if (esuf == suf)
+ return 1;
+ esuf--;
+ estr--;
+ }
+ return 0;
+}
+
+char *
+get_cwd(void)
+{
+ char *ret;
+ unsigned path_max;
+ char buf[128];
+
+ errno = 0;
+ ret = getcwd(buf, sizeof(buf));
+ if (ret != NULL)
+ return estrdup(buf);
+
+ if (errno != ERANGE)
+ die(EX_FAIL, "can't get cwd: %s", strerror(errno));
+
+ path_max = 128;
+ path_max += 2; /* The getcwd docs say to do this. */
+
+ for (;;) {
+ char *cwd = emalloc(path_max);
+ errno = 0;
+ ret = getcwd(cwd, path_max);
+ if (ret)
+ break;
+ if (errno != ERANGE)
+ die(EX_FAIL, "can't get cwd: %s", strerror(errno));
+ free(cwd);
+
+ path_max += path_max / 16;
+ path_max += 32;
+ }
+ return ret;
+}
+
+/*
+if dirname == 'hooks'
+ # Naive approach
+ if basename == 'post-commit'
+ type = svn
+ elif basename == 'post-receive'
+ type = git
+ else
+ scan uplevel dirname
+ if has_dirs('branches', 'objects', 'refs', 'info')
+ type = git
+ elif has_dirs('conf', 'dav', 'db') and has_file('format')
+ type = svn
+ endif
+ endif
+endif
+
+if type == undef
+ type = default_type
+endif
+*/
+
+#define TYPE_GIT "git"
+#define TYPE_SVN "svn"
+#define TYPE_CVS "cvs"
+
+struct file_type {
+ char const *name;
+ int type;
+};
+struct vcs_files {
+ char const *vcs;
+ struct file_type *file_types;
+ int file_count;
+ int found_count;
+};
+static struct file_type git_files[] = {
+ { "branches", S_IFDIR },
+ { "objects", S_IFDIR },
+ { "refs", S_IFDIR },
+ { "info", S_IFDIR }
+};
+static struct file_type svn_files[] = {
+ { "conf", S_IFDIR },
+ { "dav", S_IFDIR },
+ { "db", S_IFDIR },
+ { "format", S_IFREG }
+};
+static struct vcs_files vcs_files[] = {
+ { "git", git_files, sizeof(git_files)/sizeof(git_files[0]) },
+ { "svn", svn_files, sizeof(svn_files)/sizeof(svn_files[0]) },
+ { NULL }
+};
+
+static char const *
+identify_file(char const *dir, char const *file)
+{
+ struct vcs_files *vf;
+
+ for (vf = vcs_files; vf->vcs; vf++) {
+ int i;
+
+ for (i = 0; i < vf->file_count; i++) {
+ if (vf->found_count == -1)
+ continue;
+ if (strcmp (file, vf->file_types[i].name) == 0) {
+ char *fn = mkfilename(dir, file);
+ struct stat st;
+ if (stat(fn, &st))
+ continue;
+ if (st.st_mode & vf->file_types[i].type) {
+ vf->found_count++;
+ if (vf->found_count == vf->file_count)
+ return vf->vcs;
+ } else
+ vf->found_count = -1;
+ }
+ }
+ }
+ return NULL;
+}
+
+char const *
+guess_vcs_type(void)
+{
+ char *dirname, *basename;
+ char const *type = NULL;
+
+ dirname = parsefilename(fullprogname, &basename);
+ if (string_suffix(dirname, "/hooks") && basename) {
+ /* Either git or svn */
+ if (strcmp(basename, "post-receive") == 0)
+ type = TYPE_GIT;
+ else if (strcmp(basename, "post-commit") == 0)
+ type = TYPE_SVN;
+ else {
+ DIR *dir;
+ char *updir = parsefilename(dirname, NULL);
+
+ dir = opendir(updir);
+ if (dir) {
+ struct dirent *ent;
+
+ while ((ent = readdir(dir))) {
+ type = identify_file(updir,
+ ent->d_name);
+ if (type)
+ break;
+ }
+ }
+ closedir(dir);
+ free(updir);
+ }
+ }
+ return type;
+}
+
#include "cmdline.h"
@@ -96,8 +327,8 @@ main(int argc, char **argv)
setprogname(argv[0]);
config_init();
- parse_options(argc, argv, &i);
+ parse_options(argc, argv, &i);
argc -= i;
argv += i;
@@ -133,7 +364,7 @@ main(int argc, char **argv)
/* Fixup options */
if (config->detach)
stderr_only = 0;
-
+
/* Reset log_to_stderr to whatever the user wants (if -l was
given), or to the default -1.
*/
diff --git a/src/vcsync.h b/src/vcsync.h
index 88cf963..af30d4a 100644
--- a/src/vcsync.h
+++ b/src/vcsync.h
@@ -1,7 +1,24 @@
+/* This file is part of Vcsync
+ Copyright (C) 2014, 2019 Sergey Poznyakoff
+
+ Vcsync is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Vcsync is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Vcsync. If not, see <http://www.gnu.org/licenses/>.
+*/
#include <config.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
@@ -27,14 +44,16 @@
extern int debug_level;
extern int dry_run;
+extern const char *fullprogname;
extern const char *progname;
extern int log_to_stderr;
extern char *destination_root;
extern unsigned sleep_option;
extern int detach_option;
-extern char *vcs_type;
+extern char const *vcs_type;
void setprogname(const char *arg);
+void vdiag(int prio, const char *fmt, va_list ap);
void diag(int prio, const char *fmt, ...);
void debugprt(const char *fmt, ...);
void die(int ex, const char *fmt, ...);
@@ -57,8 +76,10 @@ struct vcsync_sockaddr {
};
struct vcsync_config {
+ struct vcsync_config *next;
char *name;
int debug_level;
+ char *vcs_type;
vcs_proc_fn proc;
char *vcs_command; /* FIXME: additional VCS parameters? */
char *dest_root;
@@ -72,7 +93,7 @@ struct vcsync_config {
extern struct vcsync_config default_config;
extern struct vcsync_config *config;
-extern char *config_name;
+extern char const *config_name;
extern int cfg_facility;
extern int cfg_print_priority;
@@ -116,6 +137,10 @@ int runcmd_wait(void);
char *pathcat(const char **path);
char *mkfilename(const char *dir, const char *name);
+char *parsefilename(const char *fname, char **basename);
+int string_suffix(char const *str, char const *suf);
+char const *guess_vcs_type(void);
+char *get_cwd(void);
void checkoutrc(const char *, const char *);
void register_directory(const char *dir, int recursive);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index caf577c..8c28600 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,5 +1,5 @@
# This file is part of Vcsync
-# Copyright (C) 2014 Sergey Poznyakoff
+# Copyright (C) 2014, 2019 Sergey Poznyakoff
#
# Vcsync is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/tests/atlocal.in b/tests/atlocal.in
index 2948ecc..d672b08 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -1,6 +1,6 @@
# @configure_input@ -*- shell-script -*-
# Configurable variable values for vcsync test suite.
-# Copyright (C) 2014 Sergey Poznyakoff
+# Copyright (C) 2014, 2019 Sergey Poznyakoff
PATH=@abs_builddir@:@abs_top_builddir@/src:@abs_top_srcdir@/build-aux:$top_srcdir:$srcdir:$PATH
BINDIR=@abs_top_builddir@/src
@@ -10,6 +10,7 @@ CVS_BIN=@CVS_BIN@
SVN_BIN=@SVN_BIN@
GIT_BIN=@GIT_BIN@
DFL_VCSYNC_CONF=@abs_top_srcdir@/src/vcsync.conf
+
# Return 0 if the installed CVS supports new format strings.
function cvs_format_new() {
set -- $($CVS_BIN --version | \
diff --git a/tests/checkoutrc-rec.at b/tests/checkoutrc-rec.at
index 5cf7c76..35bc6db 100644
--- a/tests/checkoutrc-rec.at
+++ b/tests/checkoutrc-rec.at
@@ -1,5 +1,5 @@
# This file is part of Vcsync testsuite. -*- Autotest -*-
-# Copyright (C) 2014 Sergey Poznyakoff
+# Copyright (C) 2014, 2019 Sergey Poznyakoff
#
# Vcsync is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -82,7 +82,8 @@ file A
# dir2/subdir/.htaccess
redirect permanent /dir2/subdir http://example.net
],
-[vcsync: [[INFO]] testing checkoutrc files
+[vcsync: [[DEBUG]] using default configuration for VCS cvs
+vcsync: [[INFO]] testing checkoutrc files
vcsync: [[DEBUG]] processing file home/test/.checkoutrc
vcsync: [[DEBUG]] processing file home/test/dir2/.checkoutrc
vcsync: [[DEBUG]] processing file home/test/dir2/subdir/.checkoutrc
diff --git a/tests/checkoutrc.at b/tests/checkoutrc.at
index 5c062fb..4eb6554 100644
--- a/tests/checkoutrc.at
+++ b/tests/checkoutrc.at
@@ -1,5 +1,5 @@
# This file is part of Vcsync testsuite. -*- Autotest -*-
-# Copyright (C) 2014 Sergey Poznyakoff
+# Copyright (C) 2014, 2019 Sergey Poznyakoff
#
# Vcsync is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -68,7 +68,8 @@ RewriteEngine On
RewriteCond expr "! %{HTTP_REFERER} -strmatch '*://%{HTTP_HOST}/*'"
RewriteRule ^/images - [[F]]
],
-[vcsync: [[INFO]] testing checkoutrc files
+[vcsync: [[DEBUG]] using default configuration for VCS cvs
+vcsync: [[INFO]] testing checkoutrc files
vcsync: [[DEBUG]] processing file home/test/.checkoutrc
])
diff --git a/tests/cvscom00.at b/tests/cvscom00.at
index 719db83..f368d7a 100644
--- a/tests/cvscom00.at
+++ b/tests/cvscom00.at
@@ -1,5 +1,5 @@
# This file is part of Vcsync testsuite. -*- Autotest -*-
-# Copyright (C) 2014 Sergey Poznyakoff
+# Copyright (C) 2014, 2019 Sergey Poznyakoff
#
# Vcsync is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -27,7 +27,13 @@ $CVS_BIN -Q commit -m 'update' > /dev/null
sleep 3
diff README ../home/test/README
],
-[0])
+[0],
+[],
+[stderr])
+
+# Remove debugging statements from stderr. They will be displayed if the
+# user sets VCSYNC_TESTSUITE_DEBUG when testing.
+AT_CHECK([sed '/vcsync: \[[DEBUG\]]/d' stderr])
AT_CLEANUP
diff --git a/tests/cvscom01.at b/tests/cvscom01.at
index 2e7aded..d54abe5 100644
--- a/tests/cvscom01.at
+++ b/tests/cvscom01.at
@@ -1,5 +1,5 @@
# This file is part of Vcsync testsuite. -*- Autotest -*-