From 903a77c857c987dd0ed645f9406df758f2ce3a1a Mon Sep 17 00:00:00 2001 From: dillon Date: Sat, 15 Sep 2001 05:57:52 +0000 Subject: Implement comprehensive CVS/Template support to complement the Template support that already exists for checkout. The -T option for cvs update and cvs checkout may be used to cause CVS to retrieve/update the checkin template when possible. MFC after: 1 week --- contrib/cvs/src/checkout.c | 15 ++++++++-- contrib/cvs/src/cvs.h | 1 + contrib/cvs/src/entries.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++ contrib/cvs/src/update.c | 26 ++++++++++++----- contrib/cvs/src/update.h | 6 +++- 5 files changed, 110 insertions(+), 11 deletions(-) (limited to 'contrib/cvs/src') diff --git a/contrib/cvs/src/checkout.c b/contrib/cvs/src/checkout.c index 86dc951..a9afa49 100644 --- a/contrib/cvs/src/checkout.c +++ b/contrib/cvs/src/checkout.c @@ -33,6 +33,10 @@ * edited by the user, if necessary (when the repository is moved, e.g.) */ +/* + * $FreeBSD$ + */ + #include #include "cvs.h" @@ -50,6 +54,7 @@ static const char *const checkout_usage[] = "\t-N\tDon't shorten module paths if -d specified.\n", "\t-P\tPrune empty directories.\n", "\t-R\tProcess directories recursively.\n", + "\t-T\tCreate Template file from local repository for remote commit.\n", "\t-c\t\"cat\" the module database.\n", "\t-f\tForce a head revision match if tag/date not found.\n", "\t-l\tLocal directory only, not recursive\n", @@ -92,6 +97,7 @@ static char *date = NULL; static char *join_rev1 = NULL; static char *join_rev2 = NULL; static int join_tags_validated = 0; +static int pull_template = 0; static char *preload_update_dir = NULL; static char *history_name = NULL; static enum mtype m_type; @@ -127,7 +133,7 @@ checkout (argc, argv) else { m_type = CHECKOUT; - valid_options = "+ANnk:d:flRpQqcsr:D:j:P"; + valid_options = "+ANnk:d:flRpTQqcsr:D:j:P"; valid_usage = checkout_usage; } @@ -156,6 +162,9 @@ checkout (argc, argv) case 'n': run_module_prog = 0; break; + case 'T': + pull_template = 1; + break; case 'Q': case 'q': #ifdef SERVER_SUPPORT @@ -1008,7 +1017,7 @@ internal error: %s doesn't start with %s in checkout_proc", force_tag_match, 0 /* !local */ , 1 /* update -d */ , aflag, checkout_prune_dirs, pipeout, which, join_rev1, join_rev2, - preload_update_dir, m_type == CHECKOUT); + preload_update_dir, pull_template); goto out; } @@ -1064,7 +1073,7 @@ internal error: %s doesn't start with %s in checkout_proc", err += do_update (argc - 1, argv + 1, options, tag, date, force_tag_match, local_specified, 1 /* update -d */, aflag, checkout_prune_dirs, pipeout, which, join_rev1, - join_rev2, preload_update_dir, m_type == CHECKOUT); + join_rev2, preload_update_dir, pull_template); out: free (preload_update_dir); preload_update_dir = oldupdate; diff --git a/contrib/cvs/src/cvs.h b/contrib/cvs/src/cvs.h index 8ce1cef..d8b5c89 100644 --- a/contrib/cvs/src/cvs.h +++ b/contrib/cvs/src/cvs.h @@ -543,6 +543,7 @@ void Scratch_Entry PROTO((List * list, char *fname)); void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp)); void WriteTag PROTO ((char *dir, char *tag, char *date, int nonbranch, char *update_dir, char *repository)); +void WriteTemplate PROTO ((char *dir, char *update_dir)); void cat_module PROTO((int status)); void check_entries PROTO((char *dir)); void close_module PROTO((DBM * db)); diff --git a/contrib/cvs/src/entries.c b/contrib/cvs/src/entries.c index 686244d..d506836 100644 --- a/contrib/cvs/src/entries.c +++ b/contrib/cvs/src/entries.c @@ -11,6 +11,9 @@ * the Entries file. */ +/* + * $FreeBSD$ + */ #include "cvs.h" #include "getline.h" @@ -633,6 +636,76 @@ AddEntryNode (list, entdata) return (p); } +static char *root_template; + +static int +get_root_template(char *repository, char *path) +{ + if (root_template) { + if (strcmp(path, root_template) == 0) + return(0); + free(root_template); + } + if ((root_template = strdup(path)) == NULL) + return(-1); + return(0); +} + +/* + * Write out/Clear the CVS/Template file. + */ +void +WriteTemplate (dir, update_dir) + char *dir; + char *update_dir; +{ + char *tmp = NULL; + char *root = NULL; + struct stat st1; + struct stat st2; + + if (Parse_Info(CVSROOTADM_RCSINFO, "cvs", get_root_template, 1) < 0) + return; + + if ((root = Name_Root(dir, update_dir)) == NULL) + error (1, errno, "unable to locate cvs root"); + if (asprintf(&tmp, "%s/%s", dir, CVSADM_TEMPLATE) < 0) + error (1, errno, "out of memory"); + + if (stat(root_template, &st1) == 0) { + if (stat(tmp, &st2) < 0 || st1.st_mtime != st2.st_mtime) { + FILE *fi; + FILE *fo; + + if ((fi = open_file(root_template, "r")) != NULL) { + if ((fo = open_file(tmp, "w")) != NULL) { + int n; + char buf[256]; + + while ((n = fread(buf, 1, sizeof(buf), fi)) > 0) + fwrite(buf, 1, n, fo); + fflush(fo); + if (ferror(fi) || ferror(fo)) { + fclose(fo); + remove(tmp); + error (1, errno, "error copying Template"); + } else { + struct timeval times[2]; + fclose(fo); + times[0].tv_sec = st1.st_mtime; + times[0].tv_usec = 0; + times[1] = times[0]; + utimes(tmp, times); + } + } + fclose(fi); + } + } + } + free(tmp); + free(root); +} + /* * Write out/Clear the CVS/Tag file. */ diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c index c92dc41..fa75977 100644 --- a/contrib/cvs/src/update.c +++ b/contrib/cvs/src/update.c @@ -98,10 +98,10 @@ static char *join_rev2, *date_rev2; static int aflag = 0; static int toss_local_changes = 0; static int force_tag_match = 1; +static int pull_template = 0; static int update_build_dirs = 0; static int update_prune_dirs = 0; static int pipeout = 0; -static int dotemplate = 0; #ifdef SERVER_SUPPORT static int patches = 0; static int rcs_diff_patches = 0; @@ -126,6 +126,7 @@ static const char *const update_usage[] = "\t-j rev\tMerge in changes made between current revision and rev.\n", "\t-I ign\tMore files to ignore (! to reset).\n", "\t-W spec\tWrappers specification line.\n", + "\t-T\tCreate CVS/Template.\n", "(Specify the --help global option for a list of other help options)\n", NULL }; @@ -141,6 +142,7 @@ update (argc, argv) int c, err; int local = 0; /* recursive by default */ int which; /* where to look for files and dirs */ + int xpull_template = 0; if (argc == -1) usage (update_usage); @@ -150,7 +152,7 @@ update (argc, argv) /* parse the args */ optind = 0; - while ((c = getopt (argc, argv, "+ApCPflRQqduk:r:D:j:I:W:")) != -1) + while ((c = getopt (argc, argv, "+ApCPflRQTqduk:r:D:j:I:W:")) != -1) { switch (c) { @@ -188,6 +190,9 @@ update (argc, argv) "-q or -Q must be specified before \"%s\"", command_name); break; + case 'T': + xpull_template = 1; + break; case 'd': update_build_dirs = 1; break; @@ -412,7 +417,8 @@ update (argc, argv) /* call the command line interface */ err = do_update (argc, argv, options, tag, date, force_tag_match, local, update_build_dirs, aflag, update_prune_dirs, - pipeout, which, join_rev1, join_rev2, (char *) NULL, 1); + pipeout, which, join_rev1, join_rev2, (char *) NULL, + xpull_template); /* free the space Make_Date allocated if necessary */ if (date != NULL) @@ -427,7 +433,7 @@ update (argc, argv) int do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir, - xdotemplate) + xpull_template) int argc; char **argv; char *xoptions; @@ -443,7 +449,7 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, char *xjoin_rev1; char *xjoin_rev2; char *preload_update_dir; - int xdotemplate; + int xpull_template; { int err = 0; char *cp; @@ -457,7 +463,7 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, aflag = xaflag; update_prune_dirs = xprune; pipeout = xpipeout; - dotemplate = xdotemplate; + pull_template = xpull_template; /* setup the join support */ join_rev1 = xjoin_rev1; @@ -968,7 +974,7 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries) via WriteTag. */ 0, 0, - dotemplate); + pull_template); rewrite_tag = 1; nonbranch = 0; Subdir_Register (entries, (char *) NULL, dir); @@ -1027,6 +1033,12 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries) nonbranch = 0; } + /* keep the CVS/Template file current */ + if (pull_template) + { + WriteTemplate (dir, update_dir); + } + /* initialize the ignore list for this directory */ ignlist = getlist (); } diff --git a/contrib/cvs/src/update.h b/contrib/cvs/src/update.h index 9a1fc00..1c3ea66 100644 --- a/contrib/cvs/src/update.h +++ b/contrib/cvs/src/update.h @@ -10,10 +10,14 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ +/* + * $FreeBSD$ + */ + int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag, char *xdate, int xforce, int local, int xbuild, int xaflag, int xprune, int xpipeout, int which, char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir, - int xdotemplate)); + int xpull_template)); int joining PROTO((void)); extern int isemptydir PROTO ((char *dir, int might_not_exist)); -- cgit v1.1