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
This commit is contained in:
parent
3471d10cbc
commit
984918456b
contrib/cvs/src
@ -33,6 +33,10 @@
|
|||||||
* edited by the user, if necessary (when the repository is moved, e.g.)
|
* edited by the user, if necessary (when the repository is moved, e.g.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "cvs.h"
|
#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-N\tDon't shorten module paths if -d specified.\n",
|
||||||
"\t-P\tPrune empty directories.\n",
|
"\t-P\tPrune empty directories.\n",
|
||||||
"\t-R\tProcess directories recursively.\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-c\t\"cat\" the module database.\n",
|
||||||
"\t-f\tForce a head revision match if tag/date not found.\n",
|
"\t-f\tForce a head revision match if tag/date not found.\n",
|
||||||
"\t-l\tLocal directory only, not recursive\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_rev1 = NULL;
|
||||||
static char *join_rev2 = NULL;
|
static char *join_rev2 = NULL;
|
||||||
static int join_tags_validated = 0;
|
static int join_tags_validated = 0;
|
||||||
|
static int pull_template = 0;
|
||||||
static char *preload_update_dir = NULL;
|
static char *preload_update_dir = NULL;
|
||||||
static char *history_name = NULL;
|
static char *history_name = NULL;
|
||||||
static enum mtype m_type;
|
static enum mtype m_type;
|
||||||
@ -127,7 +133,7 @@ checkout (argc, argv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_type = CHECKOUT;
|
m_type = CHECKOUT;
|
||||||
valid_options = "+ANnk:d:flRpQqcsr:D:j:P";
|
valid_options = "+ANnk:d:flRpTQqcsr:D:j:P";
|
||||||
valid_usage = checkout_usage;
|
valid_usage = checkout_usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +162,9 @@ checkout (argc, argv)
|
|||||||
case 'n':
|
case 'n':
|
||||||
run_module_prog = 0;
|
run_module_prog = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
pull_template = 1;
|
||||||
|
break;
|
||||||
case 'Q':
|
case 'Q':
|
||||||
case 'q':
|
case 'q':
|
||||||
#ifdef SERVER_SUPPORT
|
#ifdef SERVER_SUPPORT
|
||||||
@ -1008,7 +1017,7 @@ internal error: %s doesn't start with %s in checkout_proc",
|
|||||||
force_tag_match, 0 /* !local */ ,
|
force_tag_match, 0 /* !local */ ,
|
||||||
1 /* update -d */ , aflag, checkout_prune_dirs,
|
1 /* update -d */ , aflag, checkout_prune_dirs,
|
||||||
pipeout, which, join_rev1, join_rev2,
|
pipeout, which, join_rev1, join_rev2,
|
||||||
preload_update_dir, m_type == CHECKOUT);
|
preload_update_dir, pull_template);
|
||||||
goto out;
|
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,
|
err += do_update (argc - 1, argv + 1, options, tag, date,
|
||||||
force_tag_match, local_specified, 1 /* update -d */,
|
force_tag_match, local_specified, 1 /* update -d */,
|
||||||
aflag, checkout_prune_dirs, pipeout, which, join_rev1,
|
aflag, checkout_prune_dirs, pipeout, which, join_rev1,
|
||||||
join_rev2, preload_update_dir, m_type == CHECKOUT);
|
join_rev2, preload_update_dir, pull_template);
|
||||||
out:
|
out:
|
||||||
free (preload_update_dir);
|
free (preload_update_dir);
|
||||||
preload_update_dir = oldupdate;
|
preload_update_dir = oldupdate;
|
||||||
|
@ -543,6 +543,7 @@ void Scratch_Entry PROTO((List * list, char *fname));
|
|||||||
void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp));
|
void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp));
|
||||||
void WriteTag PROTO ((char *dir, char *tag, char *date, int nonbranch,
|
void WriteTag PROTO ((char *dir, char *tag, char *date, int nonbranch,
|
||||||
char *update_dir, char *repository));
|
char *update_dir, char *repository));
|
||||||
|
void WriteTemplate PROTO ((char *dir, char *update_dir));
|
||||||
void cat_module PROTO((int status));
|
void cat_module PROTO((int status));
|
||||||
void check_entries PROTO((char *dir));
|
void check_entries PROTO((char *dir));
|
||||||
void close_module PROTO((DBM * db));
|
void close_module PROTO((DBM * db));
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
* the Entries file.
|
* the Entries file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
#include "cvs.h"
|
#include "cvs.h"
|
||||||
#include "getline.h"
|
#include "getline.h"
|
||||||
|
|
||||||
@ -633,6 +636,76 @@ AddEntryNode (list, entdata)
|
|||||||
return (p);
|
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.
|
* Write out/Clear the CVS/Tag file.
|
||||||
*/
|
*/
|
||||||
|
@ -98,10 +98,10 @@ static char *join_rev2, *date_rev2;
|
|||||||
static int aflag = 0;
|
static int aflag = 0;
|
||||||
static int toss_local_changes = 0;
|
static int toss_local_changes = 0;
|
||||||
static int force_tag_match = 1;
|
static int force_tag_match = 1;
|
||||||
|
static int pull_template = 0;
|
||||||
static int update_build_dirs = 0;
|
static int update_build_dirs = 0;
|
||||||
static int update_prune_dirs = 0;
|
static int update_prune_dirs = 0;
|
||||||
static int pipeout = 0;
|
static int pipeout = 0;
|
||||||
static int dotemplate = 0;
|
|
||||||
#ifdef SERVER_SUPPORT
|
#ifdef SERVER_SUPPORT
|
||||||
static int patches = 0;
|
static int patches = 0;
|
||||||
static int rcs_diff_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-j rev\tMerge in changes made between current revision and rev.\n",
|
||||||
"\t-I ign\tMore files to ignore (! to reset).\n",
|
"\t-I ign\tMore files to ignore (! to reset).\n",
|
||||||
"\t-W spec\tWrappers specification line.\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",
|
"(Specify the --help global option for a list of other help options)\n",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
@ -141,6 +142,7 @@ update (argc, argv)
|
|||||||
int c, err;
|
int c, err;
|
||||||
int local = 0; /* recursive by default */
|
int local = 0; /* recursive by default */
|
||||||
int which; /* where to look for files and dirs */
|
int which; /* where to look for files and dirs */
|
||||||
|
int xpull_template = 0;
|
||||||
|
|
||||||
if (argc == -1)
|
if (argc == -1)
|
||||||
usage (update_usage);
|
usage (update_usage);
|
||||||
@ -150,7 +152,7 @@ update (argc, argv)
|
|||||||
|
|
||||||
/* parse the args */
|
/* parse the args */
|
||||||
optind = 0;
|
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)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -188,6 +190,9 @@ update (argc, argv)
|
|||||||
"-q or -Q must be specified before \"%s\"",
|
"-q or -Q must be specified before \"%s\"",
|
||||||
command_name);
|
command_name);
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
xpull_template = 1;
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
update_build_dirs = 1;
|
update_build_dirs = 1;
|
||||||
break;
|
break;
|
||||||
@ -412,7 +417,8 @@ update (argc, argv)
|
|||||||
/* call the command line interface */
|
/* call the command line interface */
|
||||||
err = do_update (argc, argv, options, tag, date, force_tag_match,
|
err = do_update (argc, argv, options, tag, date, force_tag_match,
|
||||||
local, update_build_dirs, aflag, update_prune_dirs,
|
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 */
|
/* free the space Make_Date allocated if necessary */
|
||||||
if (date != NULL)
|
if (date != NULL)
|
||||||
@ -427,7 +433,7 @@ update (argc, argv)
|
|||||||
int
|
int
|
||||||
do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
|
do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
|
||||||
xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir,
|
xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir,
|
||||||
xdotemplate)
|
xpull_template)
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
char *xoptions;
|
char *xoptions;
|
||||||
@ -443,7 +449,7 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
|
|||||||
char *xjoin_rev1;
|
char *xjoin_rev1;
|
||||||
char *xjoin_rev2;
|
char *xjoin_rev2;
|
||||||
char *preload_update_dir;
|
char *preload_update_dir;
|
||||||
int xdotemplate;
|
int xpull_template;
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
char *cp;
|
char *cp;
|
||||||
@ -457,7 +463,7 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
|
|||||||
aflag = xaflag;
|
aflag = xaflag;
|
||||||
update_prune_dirs = xprune;
|
update_prune_dirs = xprune;
|
||||||
pipeout = xpipeout;
|
pipeout = xpipeout;
|
||||||
dotemplate = xdotemplate;
|
pull_template = xpull_template;
|
||||||
|
|
||||||
/* setup the join support */
|
/* setup the join support */
|
||||||
join_rev1 = xjoin_rev1;
|
join_rev1 = xjoin_rev1;
|
||||||
@ -968,7 +974,7 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries)
|
|||||||
via WriteTag. */
|
via WriteTag. */
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
dotemplate);
|
pull_template);
|
||||||
rewrite_tag = 1;
|
rewrite_tag = 1;
|
||||||
nonbranch = 0;
|
nonbranch = 0;
|
||||||
Subdir_Register (entries, (char *) NULL, dir);
|
Subdir_Register (entries, (char *) NULL, dir);
|
||||||
@ -1027,6 +1033,12 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries)
|
|||||||
nonbranch = 0;
|
nonbranch = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* keep the CVS/Template file current */
|
||||||
|
if (pull_template)
|
||||||
|
{
|
||||||
|
WriteTemplate (dir, update_dir);
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize the ignore list for this directory */
|
/* initialize the ignore list for this directory */
|
||||||
ignlist = getlist ();
|
ignlist = getlist ();
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,14 @@
|
|||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details. */
|
GNU General Public License for more details. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag,
|
int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag,
|
||||||
char *xdate, int xforce, int local, int xbuild,
|
char *xdate, int xforce, int local, int xbuild,
|
||||||
int xaflag, int xprune, int xpipeout, int which,
|
int xaflag, int xprune, int xpipeout, int which,
|
||||||
char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir,
|
char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir,
|
||||||
int xdotemplate));
|
int xpull_template));
|
||||||
int joining PROTO((void));
|
int joining PROTO((void));
|
||||||
extern int isemptydir PROTO ((char *dir, int might_not_exist));
|
extern int isemptydir PROTO ((char *dir, int might_not_exist));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user