Index: home/ortal/ccvs/src/add.c diff -c home/ortal/ccvs/src/add.c:1.3.2.3 home/ortal/ccvs/src/add.c:1.9 *** home/ortal/ccvs/src/add.c:1.3.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/add.c Thu Jun 7 09:46:37 2007 *************** *** 181,186 **** --- 181,203 ---- special-case this. */ if (found_slash) { + #ifdef STICKY_MODULES + /* Get the module name */ + char *update_dir, *filedir, *p; + filedir = xstrdup (argv[0]); + p = last_component (filedir); + if (p == filedir) + { + update_dir = ""; + } + else + { + p[-1] = '\0'; + update_dir = filedir; + } + module_name = read_module_name(update_dir, update_dir); + #endif + repository = Name_Repository (NULL, NULL); send_a_repository ("", repository, ""); free (repository); *************** *** 244,249 **** --- 261,269 ---- rcsdir = Xasprintf ("%s/%s", repository, p); + #ifdef STICKY_MODULES + module_name = read_module_name(".", "."); + #endif Create_Admin (p, argv[j], rcsdir, tag, date, nonbranch, 0, 1); *************** *** 686,691 **** --- 706,713 ---- } skip_this_file: + if (vers) + freevers_ts (&vers); free (repository); Entries_Close (entries); *************** *** 848,854 **** --- 870,881 ---- if (server_active) WriteTemplate (finfo->fullname, 1, rcsdir); else + { + #ifdef STICKY_MODULES + module_name = read_module_name(repository, repository); + #endif Create_Admin (".", finfo->fullname, rcsdir, tag, date, nonbranch, 0, 1); + } if (tag) free (tag); Index: home/ortal/ccvs/src/admin.c diff -c home/ortal/ccvs/src/admin.c:1.2.2.3 home/ortal/ccvs/src/admin.c:1.6 *** home/ortal/ccvs/src/admin.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/admin.c Sun Jun 10 10:40:30 2007 *************** *** 211,217 **** { int err; #ifdef CVS_ADMIN_GROUP ! struct group *grp; struct group *getgrnam (const char *); #endif struct admin_data admin_data; --- 211,217 ---- { int err; #ifdef CVS_ADMIN_GROUP ! struct group *grp = NULL; struct group *getgrnam (const char *); #endif struct admin_data admin_data; *************** *** 479,484 **** --- 479,486 ---- CVS_ADMIN_GROUP); #endif } + if (grp) + free (grp); #endif /* defined CVS_ADMIN_GROUP */ for (i = 0; i < admin_data.ac; ++i) *************** *** 614,620 **** static int admin_fileproc (void *callerdat, struct file_info *finfo) { ! struct admin_data *admin_data = (struct admin_data *) callerdat; Vers_TS *vers; char *version; int i; --- 616,622 ---- static int admin_fileproc (void *callerdat, struct file_info *finfo) { ! struct admin_data *admin_data = callerdat; Vers_TS *vers; char *version; int i; *************** *** 653,665 **** if (admin_data->branch != NULL) { char *branch = &admin_data->branch[2]; ! if (*branch != '\0' && ! isdigit ((unsigned char) *branch)) { branch = RCS_whatbranch (rcs, admin_data->branch + 2); if (branch == NULL) { ! error (0, 0, "%s: Symbolic name %s is undefined.", ! rcs->path, admin_data->branch + 2); status = 1; } } --- 655,667 ---- if (admin_data->branch != NULL) { char *branch = &admin_data->branch[2]; ! if (*branch != '\0' && !isdigit ((unsigned char) *branch)) { branch = RCS_whatbranch (rcs, admin_data->branch + 2); if (branch == NULL) { ! error (0, 0, "%s: Symbolic name %s is undefined.", ! rcs->path, admin_data->branch + 2); status = 1; } } Index: home/ortal/ccvs/src/annotate.c diff -c home/ortal/ccvs/src/annotate.c:1.2.2.3 home/ortal/ccvs/src/annotate.c:1.6 *** home/ortal/ccvs/src/annotate.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/annotate.c Sun Jun 10 10:40:30 2007 *************** *** 253,259 **** static int annotate_fileproc (void *callerdat, struct file_info *finfo) { ! char *expand, *version; if (finfo->rcs == NULL) return 1; --- 253,260 ---- static int annotate_fileproc (void *callerdat, struct file_info *finfo) { ! char *expand; ! char *version = NULL; if (finfo->rcs == NULL) return 1; *************** *** 262,270 **** RCS_reparsercsfile (finfo->rcs, NULL, NULL); expand = RCS_getexpand (finfo->rcs); - version = RCS_getversion (finfo->rcs, tag, date, force_tag_match, NULL); ! if (version == NULL) return 0; /* Distinguish output for various files if we are processing --- 263,290 ---- RCS_reparsercsfile (finfo->rcs, NULL, NULL); expand = RCS_getexpand (finfo->rcs); ! /* bogus annotate behavior needs to be kept for backward compatibility */ ! if (!tag) ! version = Xasprintf (".%s", TAG_TRUNK); ! else if (RCS_is_relative (tag)) ! { ! version = Version_resolve_relTag (finfo, tag, !is_rannotate); ! if (!version) ! { ! if (!really_quiet) ! error (0, 0, "Cannot resolve relative tag: `%s'.", tag); ! return 0; ! } ! } ! else ! version = xstrdup (tag); ! ! char *tmp = version; ! version = RCS_getversion (finfo->rcs, version, date, force_tag_match, NULL); ! free (tmp); ! ! if (!version) return 0; /* Distinguish output for various files if we are processing *************** *** 279,287 **** } else { ! RCS_deltas (finfo->rcs, NULL, NULL, ! version, RCS_ANNOTATE, NULL, NULL, NULL, NULL); } free (version); return 0; } --- 299,308 ---- } else { ! RCS_deltas (finfo->rcs, NULL, NULL, ! version, RCS_ANNOTATE, NULL, NULL, NULL, NULL); } + free (version); return 0; } Index: home/ortal/ccvs/src/checkout.c diff -c home/ortal/ccvs/src/checkout.c:1.2.2.3 home/ortal/ccvs/src/checkout.c:1.5 *** home/ortal/ccvs/src/checkout.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/checkout.c Thu Jun 7 09:46:37 2007 *************** *** 394,399 **** --- 394,403 ---- } if (history_name != tag && history_name != date && history_name != NULL) free (history_name); + + if (join_orig1) free (join_orig1); + if (join_orig2) free (join_orig2); + return err; } Index: home/ortal/ccvs/src/client.c diff -c home/ortal/ccvs/src/client.c:1.3.2.3 home/ortal/ccvs/src/client.c:1.9 *** home/ortal/ccvs/src/client.c:1.3.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/client.c Thu Jun 7 09:46:37 2007 *************** *** 80,85 **** --- 80,88 ---- */ static cvsroot_t *client_referrer; + #ifdef STICKY_MODULES + char *module_name = NULL; + #endif /* We need to keep track of the list of directories we've sent to the server. This list, along with the current CVSROOT, will help us decide which command-line arguments to send. */ *************** *** 2714,2719 **** --- 2717,2732 ---- module_argv[i] = xstrdup (argv[i]); module_argv[argc] = NULL; + #ifdef STICKY_MODULES + /* First arg should be the module name. */ + if (argc < 1) + { + error(0, 0, "No module name given"); + return; + } + + module_name = xstrdup(argv[0]); + #endif for (i = 0; i < argc; ++i) send_arg (argv[i]); send_a_repository ("", current_parsed_root->directory, ""); Index: home/ortal/ccvs/src/commit.c diff -c home/ortal/ccvs/src/commit.c:1.2.2.3 home/ortal/ccvs/src/commit.c:1.17 *** home/ortal/ccvs/src/commit.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/commit.c Wed Jul 4 12:57:02 2007 *************** *** 696,701 **** --- 696,707 ---- Lock_Cleanup (); dellist (&mulist); + /* add the commitid to val-tags + */ + char *commitid = Xasprintf ("@%s", global_session_id); + tag_check_valid (commitid, argc, argv, local, aflag, "", true); + free (commitid); + /* see if we need to sleep before returning to avoid time-stamp races */ if (!server_active && last_register_time) { *************** *** 894,899 **** --- 900,923 ---- finfo->fullname); goto out; } + if (status == T_MODIFIED && !force_ci && vers->ts_conflict) + { + /* + * We found a "conflict" marker. + * + * If the timestamp on the file is the same as the + * timestamp stored in the Entries file, we block the commit. + */ + if ( file_has_conflict ( finfo, vers->ts_conflict ) ) + { + error (0, 0, + "file `%s' had a conflict and has not been modified", + finfo->fullname); + freevers_ts (&vers); + return (1); + } + + } if (status == T_MODIFIED && !force_ci && file_has_markers (finfo)) { /* Make this a warning, not an error, because we have *************** *** 907,915 **** keyword expansion, because there is no -ko analogue. */ error (0, 0, ! "\ warning: file `%s' seems to still contain conflict indicators", ! finfo->fullname); } if (status == T_REMOVED) --- 931,939 ---- keyword expansion, because there is no -ko analogue. */ error (0, 0, ! "\ warning: file `%s' seems to still contain conflict indicators", ! finfo->fullname); } if (status == T_REMOVED) *************** *** 1042,1047 **** --- 1066,1073 ---- error (0, 0, "Valid edit does not exist for %s", finfo->fullname); freevers_ts (&vers); + if (li) free (li); + if (p) freenode (p); return 1; } *************** *** 1049,1055 **** li->rev_old = xstrdup (vers->vn_rcs); li->rev_new = NULL; p->data = li; ! (void) addnode (ulist, p); p = getnode (); p->key = xstrdup (finfo->file); --- 1075,1081 ---- li->rev_old = xstrdup (vers->vn_rcs); li->rev_new = NULL; p->data = li; ! if (addnode (ulist, p)) freenode (p); p = getnode (); p->key = xstrdup (finfo->file); *************** *** 1225,1230 **** --- 1251,1260 ---- char *cmdline; const char *srepos = Short_Repository (repository); List *ulist = closure; + char *log_message_escaped; + + log_message_escaped = xmalloc(strlen(saved_message)*2+1); + shell_escape(log_message_escaped, saved_message); #ifdef SUPPORT_OLD_INFO_FMT_STRINGS if (!strchr (filter, '%')) *************** *** 1254,1259 **** --- 1284,1295 ---- "R", "s", referrer ? referrer->original : "NONE", #endif /* SERVER_SUPPORT */ "p", "s", srepos, + + /* A "%m" at the end of the filter indicates that + * the log message is to be sent to the filter + * (will be sent as argv[1]). + */ + "m", "s", log_message_escaped, "r", "s", current_parsed_root->directory, "s", ",", ulist, precommit_list_to_args_proc, (void *) NULL, *************** *** 1264,1275 **** --- 1300,1313 ---- if (!cmdline || !strlen (cmdline)) { if (cmdline) free (cmdline); + free (log_message_escaped); error (0, 0, "precommit proc resolved to the empty string!"); return 1; } run_setup (cmdline); free (cmdline); + free (log_message_escaped); return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL | RUN_REALLY); } *************** *** 1311,1317 **** --- 1349,1384 ---- return err; } + /* for soft branches, we delay putting the branch on the RCS file + * for real. Only when we need to create real revisions on the + * branch do we need to create the branch tag on file. + */ + void + checkmodfile(struct file_info *finfo, char *tag, char**rev) + { + Soft_Tag *soft_tag; + + if ((soft_tag = tag_is_soft (finfo->rcs, tag, 1)) && + soft_tag->is_branch && !*rev) + { + char *magicrev; + + /* find the magic revision */ + magicrev = RCS_magicrev (finfo->rcs, RCS_tag2rev (finfo->rcs, tag)); + + /* put branch on RCS */ + if (RCS_settag (finfo->rcs, tag, magicrev)) + error (1, 0, "failed to create tag for soft branch %s", tag); + + /* make the soft-branch a hard-branch in this file */ + RCS_rewrite (finfo->rcs, NULL, NULL); + /* find branch to use for the checkin according to magic revision + */ + *rev = RCS_whatbranch (finfo->rcs, RCS_tag2rev (finfo->rcs, tag)); + free (magicrev); + } + } /* * Do the work of committing a file *************** *** 1459,1464 **** --- 1526,1532 ---- } else if (ci->status == T_MODIFIED) { + checkmodfile(finfo, ci->tag, &ci->rev); err = Checkin ('M', finfo, ci->rev, ci->tag, ci->options, saved_message); *************** *** 1754,1768 **** if (branch) { char *branchname; rev = RCS_whatbranch (finfo->rcs, tag); ! if (rev == NULL) { error (0, 0, "cannot find branch \"%s\".", tag); return 1; } ! branchname = RCS_getbranch (finfo->rcs, rev, 1); if (branchname == NULL) { /* no revision exists on this branch. use the previous --- 1822,1841 ---- if (branch) { char *branchname; + int soft_branch = 0; rev = RCS_whatbranch (finfo->rcs, tag); ! if (!rev) ! soft_branch = tag_is_soft(finfo->rcs, tag, 0) != NULL; ! if (rev == NULL && !soft_branch) { error (0, 0, "cannot find branch \"%s\".", tag); return 1; } + if (soft_branch) + checkmodfile (finfo, tag, &rev); ! branchname = soft_branch ? NULL : RCS_getbranch (finfo->rcs, rev, 1); if (branchname == NULL) { /* no revision exists on this branch. use the previous *************** *** 1798,1804 **** /* check something out. Generally this is the head. If we have a particular rev, then name it. */ ! retcode = RCS_checkout (finfo->rcs, finfo->file, rev ? corev : NULL, NULL, NULL, RUN_TTY, NULL, NULL); if (retcode != 0) { --- 1871,1878 ---- /* check something out. Generally this is the head. If we have a particular rev, then name it. */ ! retcode = RCS_checkout (finfo->rcs, finfo->file, ! rev ? corev : NULL, NULL, NULL, RUN_TTY, NULL, NULL); if (retcode != 0) { *************** *** 1831,1839 **** probably tell the history file about it */ history_write ('R', NULL, finfo->rcs->head, finfo->file, finfo->repository); - if (rev != NULL) - free (rev); - old_path = xstrdup (finfo->rcs->path); if (!branch) RCS_setattic (finfo->rcs, 1); --- 1905,1910 ---- *************** *** 1849,1860 **** cvs_output ("/", 1); } cvs_output (finfo->file, 0); ! cvs_output ("\nnew revision: delete; previous revision: ", 0); cvs_output (prev_rev, 0); cvs_output ("\n", 0); } free (prev_rev); free (old_path); --- 1920,1939 ---- cvs_output ("/", 1); } cvs_output (finfo->file, 0); ! cvs_output ("\nnew revision: delete", 0); ! if (commit_show_deleted_ver) ! { ! cvs_output (" ", 0); ! cvs_output (RCS_getversion (finfo->rcs, rev, NULL, 0, NULL), 0); ! } ! cvs_output ("; previous revision: ", 0); cvs_output (prev_rev, 0); cvs_output ("\n", 0); } free (prev_rev); + if (rev != NULL) + free (rev); free (old_path); *************** *** 2138,2147 **** /* when adding a file for the first time, and using a tag, we need to create a dead revision on the trunk. */ ! if (adding_on_branch) { - if (newfile) - { char *tmp; FILE *fp; int retcode; --- 2217,2224 ---- /* when adding a file for the first time, and using a tag, we need to create a dead revision on the trunk. */ ! if (newfile && (adding_on_branch || create_trunk_dead_rev)) { char *tmp; FILE *fp; int retcode; *************** *** 2158,2166 **** if (fclose (fp) < 0) error (0, errno, "cannot close %s", file); - tmp = Xasprintf ("file %s was initially added on branch %s.", - file, tag); /* commit a dead revision. */ retcode = RCS_checkin (rcs, NULL, NULL, tmp, NULL, 0, RCS_FLAGS_DEAD | RCS_FLAGS_QUIET); free (tmp); --- 2235,2246 ---- if (fclose (fp) < 0) error (0, errno, "cannot close %s", file); /* commit a dead revision. */ + if (adding_on_branch) + tmp = Xasprintf ("file %s was initially added on branch %s.", + file, tag); + else + tmp = Xasprintf ("file %s was initially added on trunk.", file); retcode = RCS_checkin (rcs, NULL, NULL, tmp, NULL, 0, RCS_FLAGS_DEAD | RCS_FLAGS_QUIET); free (tmp); *************** *** 2193,2205 **** rcs->path); goto out; } ! } /* when adding with a tag, we need to stub a branch, if it doesn't already exist. */ ! if (!RCS_nodeisbranch (rcs, tag)) { /* branch does not exist. Stub it. */ char *head; char *magicrev; int retcode; --- 2273,2289 ---- rcs->path); goto out; } ! } + if (adding_on_branch) + { /* when adding with a tag, we need to stub a branch, if it doesn't already exist. */ ! if (!RCS_nodeisbranch (rcs, tag) || tag_is_soft (rcs, tag, 0)) { /* branch does not exist. Stub it. */ + /* branching point may be BASE or HEAD, + according to BranchFromBaseRev */ char *head; char *magicrev; int retcode; *************** *** 2211,2217 **** fixbranch (rcs, sbranch); ! head = RCS_getversion (rcs, NULL, NULL, 0, NULL); if (!head) error (1, 0, "No head revision in archive file `%s'.", rcs->print_path); --- 2295,2304 ---- fixbranch (rcs, sbranch); ! if (branch_from_base_rev) ! head = xstrdup("1.1"); ! else ! head = RCS_getversion (rcs, NULL, NULL, 0, (int *) NULL); if (!head) error (1, 0, "No head revision in archive file `%s'.", rcs->print_path); *************** *** 2219,2226 **** /* If this is not a new branch, then we will want a dead version created before this one. */ ! if (!newfile) headtime = RCS_getrevtime (rcs, head, 0, 0); retcode = RCS_settag (rcs, tag, magicrev); RCS_rewrite (rcs, NULL, NULL); --- 2306,2326 ---- /* If this is not a new branch, then we will want a dead version created before this one. */ ! ! /* The correct behaviour is: ! * if we are branching from 1.1 and it's already dead, don't need ! * to create additional dead revision on the new branch. ! * We activate this behavior on CreateTrunkDeadRev=y. ! * If CreateTrunkDeadRev=n (original CVS-1.12.13 ! * behaviour), then we add a dead revision on the branch even ! * if 1.1 is already dead. We hope that in CVS open-source they ! * will fix this soon to Jungo's behaviour. ! */ ! if (!newfile && (!create_trunk_dead_rev || ! !(!strcmp(head, "1.1") && RCS_isdead(rcs, "1.1")))) ! { headtime = RCS_getrevtime (rcs, head, 0, 0); + } retcode = RCS_settag (rcs, tag, magicrev); RCS_rewrite (rcs, NULL, NULL); *************** *** 2429,2434 **** --- 2529,2536 ---- { struct logfile_info *li = p->data; + if (!li) + return; if (li->tag) free (li->tag); if (li->rev_old) Index: home/ortal/ccvs/src/create_adm.c diff -c home/ortal/ccvs/src/create_adm.c:1.3.2.3 home/ortal/ccvs/src/create_adm.c:1.9 *** home/ortal/ccvs/src/create_adm.c:1.3.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/create_adm.c Thu Jun 7 09:46:37 2007 *************** *** 164,169 **** --- 164,199 ---- WriteTag (dir, tag, date, nonbranch, update_dir, repository); TRACE (TRACE_FUNCTION, "Create_Admin"); + #ifdef STICKY_MODULES + if (!server_active && module_name) + { + /* Create the ModuleName file */ + if (dir != NULL) + (void) sprintf (tmp, "%s/%s", dir, CVSADM_MODULE_NAME); + else + (void) strcpy (tmp, CVSADM_MODULE_NAME); + fout = CVS_FOPEN (tmp, "w+"); + if (fout == NULL) + { + if (update_dir[0] == '\0') + error (1, errno, "cannot open %s", tmp); + else + { + error (1, errno, "cannot open %s/%s", update_dir, + CVSADM_MODULE_NAME); + } + } + fprintf(fout, "%s\n", module_name); + if (fclose (fout) == EOF) + { + if (update_dir[0] == '\0') + error (1, errno, "cannot close %s", tmp); + else + error (1, errno, "cannot close %s/%s", update_dir, + CVSADM_ENT); + } + } + #endif free (reposcopy); free (tmp); Index: home/ortal/ccvs/src/cvs.h diff -c home/ortal/ccvs/src/cvs.h:1.4.2.3 home/ortal/ccvs/src/cvs.h:1.36 *** home/ortal/ccvs/src/cvs.h:1.4.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/cvs.h Sun Jul 8 19:22:56 2007 *************** *** 16,21 **** --- 16,29 ---- * */ + #define JUNGO_VERSION "-jungo-12" + extern int disable_import; + extern int create_trunk_dead_rev; + extern int branch_from_base_rev; + extern int merge_binary_identical; + extern int merge_add_to_nondead; + extern int status_show_module; + extern int commit_show_deleted_ver; #ifdef HAVE_CONFIG_H # include /* this is stuff found via autoconf */ *************** *** 64,70 **** --- 72,81 ---- /* end GNULIB headers */ #if ! STDC_HEADERS + extern void exit (); char *getenv(); + #else + #include #endif /* ! STDC_HEADERS */ /* Under OS/2, doesn't define popen()/pclose(). */ *************** *** 72,83 **** --- 83,114 ---- #include "popen.h" #endif + #ifdef HAVE_UNISTD_H + #include + #endif + + #ifdef HAVE_STRING_H + #include + #else + #include + #endif + #ifdef SERVER_SUPPORT /* If the system doesn't provide strerror, it won't be declared in string.h. */ char *strerror (int); #endif + #include /* This is supposed to be available on Posix systems */ + + #ifdef HAVE_ERRNO_H + #include + #else + #ifndef errno + extern int errno; + #endif /* !errno */ + #endif /* HAVE_ERRNO_H */ + #include "hash.h" #include "stack.h" *************** *** 110,115 **** --- 141,149 ---- /* Definitions for the CVS Administrative directory and the files it contains. Here as #define's to make changing the names a simple task. */ + #ifdef STICKY_MODULES + #define CVSADM_MODULE_NAME "CVS/Module." + #endif #ifdef USE_VMS_FILENAMES #define CVSADM "CVS" #define CVSADM_ENT "CVS/Entries." *************** *** 184,189 **** --- 218,224 ---- #define CVSROOTADM_VERIFYMSG "verifymsg" #define CVSROOTADM_WRAPPER "cvswrappers" #define CVSROOTADM_WRITERS "writers" + #define CVSROOTADM_STAGS "stags" #define CVSNULLREPOS "Emptydir" /* an empty directory */ *************** *** 237,244 **** --- 272,283 ---- #ifdef USE_VMS_FILENAMES # define BAKPREFIX "_$" + #define DEVNULL "NLA0:" #else /* USE_VMS_FILENAMES */ # define BAKPREFIX ".#" /* when rcsmerge'ing */ + #ifndef DEVNULL + #define DEVNULL "/dev/null" + #endif #endif /* USE_VMS_FILENAMES */ /* *************** *** 248,253 **** --- 287,302 ---- */ #define TAG_HEAD "HEAD" #define TAG_BASE "BASE" + #define TAG_DOTHEAD "head" + #define TAG_DOTBASE "base" + #define TAG_COMMITID "commitid" + #define TAG_PREVIOUS "prev" + #define TAG_TRUNK "trunk" + #define TAG_ORIGIN "origin" + #define TAG_ROOT "root" + #define TAG_NEXT "next" + /* if tag is a soft tag, ignore any occurences of it in RCS */ + #define TAG_SOFT "soft" /* Environment variable used by CVS */ #define CVSREAD_ENV "CVSREAD" /* make files read-only */ *************** *** 263,272 **** #define EDITOR3_ENV "EDITOR" /* which editor to use */ #define CVSROOT_ENV "CVSROOT" /* source directory root */ ! /* Define CVSROOT_DFLT to a fallback value for CVSROOT. ! * ! #undef CVSROOT_DFL ! */ #define IGNORE_ENV "CVSIGNORE" /* More files to ignore */ #define WRAPPER_ENV "CVSWRAPPERS" /* name of the wrapper file */ --- 312,318 ---- #define EDITOR3_ENV "EDITOR" /* which editor to use */ #define CVSROOT_ENV "CVSROOT" /* source directory root */ ! #define CVSROOT_DFLT NULL /* No dflt; must set for checkout */ #define IGNORE_ENV "CVSIGNORE" /* More files to ignore */ #define WRAPPER_ENV "CVSWRAPPERS" /* name of the wrapper file */ *************** *** 371,376 **** --- 417,425 ---- extern int use_editor; extern int cvswrite; extern mode_t cvsumask; + #ifdef STICKY_MODULES + extern char *module_name; + #endif /* Temp dir abstraction. */ /* From main.c. */ *************** *** 385,394 **** from the CVSROOT environment variable or from a CVS/Root file. */ extern char *CVSroot_cmdline; ! /* This variable keeps track of all of the CVSROOT directories that ! * have been seen by the client. */ extern List *root_directories; char *emptydir_name (void); int safe_location (char *); --- 434,444 ---- from the CVSROOT environment variable or from a CVS/Root file. */ extern char *CVSroot_cmdline; ! /* These variables keep track of all of the CVSROOT directories that ! * have been seen by the client and the current one of those selected. */ extern List *root_directories; + extern cvsroot_t *current_parsed_root; char *emptydir_name (void); int safe_location (char *); *************** *** 476,481 **** --- 526,535 ---- const char *Short_Repository (const char *repository); void Sanitize_Repository_Name (char *repository); + #ifdef STICKY_MODULES + char * read_module_name(char *dir, char *update_dir); + #endif + char *entries_time (time_t unixtime); time_t unix_time_stamp (const char *file); char *time_stamp (const char *file); *************** *** 509,531 **** struct file_info { /* Name of the file, without any directory component. */ ! const char *file; /* Name of the directory we are in, relative to the directory in which this command was issued. We have cd'd to this directory (either in the working directory or in the repository, depending on which sort of recursion we are doing). If we are in the directory in which the command was issued, this is "". */ ! const char *update_dir; /* update_dir and file put together, with a slash between them as necessary. This is the proper way to refer to the file in user messages. */ ! const char *fullname; /* Name of the directory corresponding to the repository which contains this file. */ ! const char *repository; /* The pre-parsed entries for this directory. */ List *entries; --- 563,585 ---- struct file_info { /* Name of the file, without any directory component. */ ! char *file; /* Name of the directory we are in, relative to the directory in which this command was issued. We have cd'd to this directory (either in the working directory or in the repository, depending on which sort of recursion we are doing). If we are in the directory in which the command was issued, this is "". */ ! char *update_dir; /* update_dir and file put together, with a slash between them as necessary. This is the proper way to refer to the file in user messages. */ ! char *fullname; /* Name of the directory corresponding to the repository which contains this file. */ ! char *repository; /* The pre-parsed entries for this directory. */ List *entries; *************** *** 667,672 **** --- 721,729 ---- int SIG_inCrSect (void); void read_cvsrc (int *argc, char ***argv, const char *cmdname); + extern int file_has_conflict (struct file_info *, char *ts_conflict); + extern int file_has_markers (const struct file_info *); + /* flags for run_exec(), the fast system() for CVS */ #define RUN_NORMAL 0x0000 /* no special behaviour */ #define RUN_COMBINED 0x0001 /* stdout is duped to stderr */ *************** *** 766,771 **** --- 823,830 ---- char *date, int force_tag_match, int set_time); void freevers_ts (Vers_TS ** versp); + char *Version_resolve_relTag (struct file_info *, const char *, bool); + /* Miscellaneous CVS infrastructure which layers on top of the recursion processor (for example, needs struct file_info). */ *************** *** 907,912 **** --- 966,988 ---- void tag_check_valid (const char *, int, char **, int, int, char *, bool); + typedef struct soft_tag Soft_Tag; + struct soft_tag + { + int is_branch; + /* name of tag */ + char *tag; + + /* position of tag: either branch+date or tag */ + char *onsymbol; + char *date; + /* sub-tree where tag can be applied */ + char *repository; + }; + + Soft_Tag *tag_is_soft(RCSNode *rcs, const char *tag, int check_repository); + void soft_tags_free(void); + #include "server.h" /* From server.c and documented there. */ Index: home/ortal/ccvs/src/diff.c diff -c home/ortal/ccvs/src/diff.c:1.2.2.3 home/ortal/ccvs/src/diff.c:1.5 *** home/ortal/ccvs/src/diff.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/diff.c Thu Jun 7 09:46:37 2007 *************** *** 468,473 **** --- 468,481 ---- free (diff_date1); if (diff_date2 != NULL) free (diff_date2); + if (diff_orig1) + free (diff_orig1); + if (diff_orig1) + free (diff_orig2); + if (diff_rev1) + free (diff_rev1); + if (diff_rev2) + free (diff_rev2); return err; } Index: home/ortal/ccvs/src/edit.c diff -c home/ortal/ccvs/src/edit.c:1.2.2.3 home/ortal/ccvs/src/edit.c:1.5 *** home/ortal/ccvs/src/edit.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/edit.c Thu Jun 7 09:46:37 2007 *************** *** 32,38 **** static int onoff_fileproc (void *callerdat, struct file_info *finfo) { ! fileattr_get0 (finfo->file, "_watched"); fileattr_set (finfo->file, "_watched", turning_on ? "" : NULL); return 0; } --- 32,38 ---- static int onoff_fileproc (void *callerdat, struct file_info *finfo) { ! free (fileattr_get0 (finfo->file, "_watched")); fileattr_set (finfo->file, "_watched", turning_on ? "" : NULL); return 0; } *************** *** 45,51 **** { if (setting_default) { ! fileattr_get0 (NULL, "_watched"); fileattr_set (NULL, "_watched", turning_on ? "" : NULL); } return err; --- 45,51 ---- { if (setting_default) { ! free (fileattr_get0 (NULL, "_watched")); fileattr_set (NULL, "_watched", turning_on ? "" : NULL); } return err; *************** *** 305,310 **** --- 305,311 ---- editors_output (finfo->fullname, them); + free (them); return 0; } *************** *** 364,369 **** --- 365,371 ---- if (!vers->vn_user) { error (0, 0, "no such file %s; ignored", finfo->fullname); + freevers_ts (&vers); return 1; } *************** *** 385,390 **** --- 387,394 ---- if (!really_quiet) error (0, 0, "Skipping file `%s' due to existing editors.", finfo->fullname); + free (editors); + freevers_ts (&vers); return 1; } free (editors); *************** *** 432,437 **** --- 436,442 ---- #endif /* SERVER_SUPPORT */ edit_file (NULL, finfo->entries, finfo->fullname, finfo->file); + freevers_ts (&vers); return 0; } Index: home/ortal/ccvs/src/filesubr.c diff -c home/ortal/ccvs/src/filesubr.c:1.2.2.3 home/ortal/ccvs/src/filesubr.c:1.6 *** home/ortal/ccvs/src/filesubr.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/filesubr.c Thu Jun 7 09:46:38 2007 *************** *** 63,74 **** else { /* Not a link or a device... probably a regular file. */ ! if ((fdin = open (from, O_RDONLY)) < 0) error (1, errno, "cannot open %s for copying", from); if (fstat (fdin, &sb) < 0) error (1, errno, "cannot fstat %s", from); if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0) error (1, errno, "cannot create %s for copying", to); if (sb.st_size > 0) { char buf[BUFSIZ]; --- 63,77 ---- else { /* Not a link or a device... probably a regular file. */ ! if ((fdin = open (from, O_RDONLY | OPEN_BINARY)) < 0) error (1, errno, "cannot open %s for copying", from); if (fstat (fdin, &sb) < 0) error (1, errno, "cannot fstat %s", from); if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0) error (1, errno, "cannot create %s for copying", to); + #ifdef HAVE_SETMODE + setmode (fdout, O_BINARY); + #endif if (sb.st_size > 0) { char buf[BUFSIZ]; Index: home/ortal/ccvs/src/find_names.c diff -c home/ortal/ccvs/src/find_names.c:1.2.2.2 home/ortal/ccvs/src/find_names.c:1.3 *** home/ortal/ccvs/src/find_names.c:1.2.2.2 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/find_names.c Thu Jun 7 09:46:38 2007 *************** *** 324,331 **** --- 324,334 ---- if (err && err != GLOB_NOMATCH) { if (err == GLOB_ABORTED) + { /* Let our caller handle the problem. */ + if (catpat) free (catpat); return NULL; + } if (err == GLOB_NOSPACE) errno = ENOMEM; if (!really_quiet) error (0, errno, "glob failed"); Index: home/ortal/ccvs/src/hash.c diff -c home/ortal/ccvs/src/hash.c:1.2.2.3 home/ortal/ccvs/src/hash.c:1.5 *** home/ortal/ccvs/src/hash.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/hash.c Thu Jun 7 09:46:38 2007 *************** *** 170,176 **** { n = p->next; removenode (p); ! addnode (dest, p); } dellist (src); } --- 170,176 ---- { n = p->next; removenode (p); ! if (addnode (dest, p)) freenode(p); } dellist (src); } Index: home/ortal/ccvs/src/history.c diff -c home/ortal/ccvs/src/history.c:1.2.2.3 home/ortal/ccvs/src/history.c:1.5 *** home/ortal/ccvs/src/history.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/history.c Thu Jun 7 09:46:38 2007 *************** *** 376,382 **** /* Get the name of the history log, either from CVSROOT/config, or via the * hard-coded default. */ ! static const char * get_history_log_name (time_t now) { char *log_name; --- 376,382 ---- /* Get the name of the history log, either from CVSROOT/config, or via the * hard-coded default. */ ! static char * get_history_log_name (time_t now) { char *log_name; *************** *** 412,417 **** --- 412,440 ---- + /* go over all history records in array pointed by hrec_head, + * and free the allocated memory. + */ + static void + free_hrecs(void) + { + struct hrec *hr; + + if (!hrec_head) + return; + + /* hrec_head points to array of hrec */ + /* hrline string is parsed into hrec fields, starting at type, + * (this is done in fill_hrec) + * so freeing type alone is sufficient + */ + for (hr = hrec_head; (hr < hrec_head + hrec_max) && hr->type; hr++) + free (hr->type); + free (hrec_head); + } + + + int history (int argc, char **argv) { *************** *** 744,749 **** --- 767,774 ---- if (hrec_count > 0) qsort (hrec_head, hrec_count, sizeof (struct hrec), sort_order); report_hrecs (); + free_hrecs (); + dellist (&flist); if (since_date != NULL) free (since_date); free (since_rev); *************** *** 762,768 **** history_write (int type, const char *update_dir, const char *revs, const char *name, const char *repository) { ! const char *fname; char *workdir; char *username = getcaller (); int fd; --- 787,793 ---- history_write (int type, const char *update_dir, const char *revs, const char *name, const char *repository) { ! char *fname; char *workdir; char *username = getcaller (); int fd; *************** *** 937,942 **** --- 962,969 ---- free (workdir); out: clear_history_lock (); + if (fname) + free(fname); } *************** *** 1175,1180 **** --- 1202,1209 ---- hrec_max += HREC_INCREMENT; hrec_head = xnrealloc (hrec_head, hrec_max, sizeof (struct hrec)); + memset (hrec_head, 0, hrec_max); + if (last_since_tag) last_since_tag = hrec_head + (last_since_tag - old_head); if (last_backto) *************** *** 1191,1198 **** fill_hrec (hrline, &hrec_head[hrec_count]); if (select_hrec (&hrec_head[hrec_count])) hrec_count++; ! else free (hrline); cp = nl + 1; } --- 1220,1230 ---- fill_hrec (hrline, &hrec_head[hrec_count]); if (select_hrec (&hrec_head[hrec_count])) hrec_count++; ! else ! { free (hrline); + hrec_head[hrec_count].type = NULL; + } cp = nl + 1; } *************** *** 1214,1219 **** --- 1246,1252 ---- */ hrec_max = HREC_INCREMENT; hrec_head = xmalloc (hrec_max * sizeof (struct hrec)); + memset(hrec_head, 0, hrec_max * sizeof (struct hrec)); hrec_idx = 0; files_read = walklist (flist, read_hrecs_file, NULL); Index: home/ortal/ccvs/src/ignore.c diff -c home/ortal/ccvs/src/ignore.c:1.3.2.3 home/ortal/ccvs/src/ignore.c:1.9 *** home/ortal/ccvs/src/ignore.c:1.3.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/ignore.c Thu Jun 7 09:46:38 2007 *************** *** 335,341 **** while (i--) { if (strncmp (name, dir_ign_list[i], strlen (dir_ign_list[i])+1) == 0) ! return 1; } return 0; --- 335,345 ---- while (i--) { if (strncmp (name, dir_ign_list[i], strlen (dir_ign_list[i])+1) == 0) ! #ifdef STICKY_MODULES ! if ( strlen(name) == strlen(dir_ign_list[i]) ! || name[strlen(dir_ign_list[i])] == '/') ! #endif ! return 1; } return 0; Index: home/ortal/ccvs/src/import.c diff -c home/ortal/ccvs/src/import.c:1.2.2.3 home/ortal/ccvs/src/import.c:1.9 *** home/ortal/ccvs/src/import.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/import.c Sun Jun 10 10:40:34 2007 *************** *** 84,89 **** --- 84,92 ---- if (argc == -1) usage (import_usage); + if (disable_import) + error(1, 0, "Jungo disabled 'cvs import'. use 'jcvs importprep' instead."); + /* Force -X behaviour or not based on the CVS repository CVSROOT/config setting. */ #ifdef CLIENT_SUPPORT *************** *** 430,435 **** --- 433,442 ---- error (0, errno, "cannot remove %s", tmpfile); free (tmpfile); + char *commitid = Xasprintf ("@%s", global_session_id); + tag_check_valid (commitid, argc, argv, 0, 1, "", true); + free (commitid); + if (message) free (message); free (repository); *************** *** 1469,1474 **** --- 1476,1483 ---- error (0, errno, "cannot remove %s", tocvsPath); if (free_opt != NULL) free (free_opt); + if (dead_revision) + free (dead_revision); return err; write_error: *************** *** 1496,1501 **** --- 1505,1512 ---- if (free_opt != NULL) free (free_opt); + if (dead_revision) + free (dead_revision); return err + 1; } Index: home/ortal/ccvs/src/lock.c diff -c home/ortal/ccvs/src/lock.c:1.2.2.3 home/ortal/ccvs/src/lock.c:1.7 *** home/ortal/ccvs/src/lock.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/lock.c Thu Jun 7 09:46:38 2007 *************** *** 152,158 **** static List *lock_tree_list; - /* Return a newly malloc'd string containing the name of the lock for the repository REPOSITORY and the lock file name within that directory NAME. Also create the directories in which to put the lock file --- 152,157 ---- *************** *** 184,199 **** { struct stat sb; mode_t new_mode = 0; /* The interesting part of the repository is the part relative to CVSROOT. */ assert (current_parsed_root != NULL); assert (current_parsed_root->directory != NULL); ! assert (strncmp (repository, current_parsed_root->directory, ! strlen (current_parsed_root->directory)) == 0); ! short_repos = repository + strlen (current_parsed_root->directory) + 1; ! if (strcmp (repository, current_parsed_root->directory) == 0) short_repos = "."; else assert (short_repos[-1] == '/'); --- 183,207 ---- { struct stat sb; mode_t new_mode = 0; + size_t parsed_root_len = 0; /* The interesting part of the repository is the part relative to CVSROOT. */ assert (current_parsed_root != NULL); assert (current_parsed_root->directory != NULL); ! if (current_parsed_root->dirpath != NULL); ! parsed_root_len = strlen (current_parsed_root->dirpath); ! if (parsed_root_len == 0 || ! strncmp (repository, current_parsed_root->dirpath, ! parsed_root_len) != 0) ! { ! parsed_root_len = strlen (current_parsed_root->directory); ! assert (strncmp (repository, current_parsed_root->directory, ! parsed_root_len) == 0); ! } ! short_repos = repository + parsed_root_len + 1; ! if (short_repos[-1] == '\0') short_repos = "."; else assert (short_repos[-1] == '/'); Index: home/ortal/ccvs/src/log.c diff -c home/ortal/ccvs/src/log.c:1.2.2.3 home/ortal/ccvs/src/log.c:1.6 *** home/ortal/ccvs/src/log.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/log.c Sun Jun 10 10:40:34 2007 *************** *** 128,134 **** static struct option_revlist *log_parse_revlist (const char *); static void log_parse_date (struct log_data *, const char *); static void log_parse_list (List **, const char *); ! static struct revlist *log_expand_revlist (RCSNode *, char *, struct option_revlist *, int); static void log_free_revlist (struct revlist *); static int log_version_requested (struct log_data *, struct revlist *, --- 128,134 ---- static struct option_revlist *log_parse_revlist (const char *); static void log_parse_date (struct log_data *, const char *); static void log_parse_list (List **, const char *); ! static struct revlist *log_expand_revlist (struct file_info *, char *, struct option_revlist *, int); static void log_free_revlist (struct revlist *); static int log_version_requested (struct log_data *, struct revlist *, *************** *** 842,848 **** /* Turn any symbolic revisions in the revision list into numeric revisions. */ ! revlist = log_expand_revlist (rcsfile, baserev, log_data->revlist, log_data->default_branch); if (log_data->sup_header || (!log_data->header && !log_data->long_header)) --- 842,848 ---- /* Turn any symbolic revisions in the revision list into numeric revisions. */ ! revlist = log_expand_revlist (finfo, baserev, log_data->revlist, log_data->default_branch); if (log_data->sup_header || (!log_data->header && !log_data->long_header)) *************** *** 1032,1043 **** * Expand any symbolic revisions. */ static struct revlist * ! log_expand_revlist (RCSNode *rcs, char *baserev, struct option_revlist *revlist, int default_branch) { struct option_revlist *r; struct revlist *ret, **pr; ! ret = NULL; pr = &ret; for (r = revlist; r != NULL; r = r->next) --- 1032,1045 ---- * Expand any symbolic revisions. */ static struct revlist * ! log_expand_revlist (struct file_info *finfo, char *baserev, struct option_revlist *revlist, int default_branch) { struct option_revlist *r; struct revlist *ret, **pr; ! char *first = NULL; ! char *last = NULL; ! RCSNode *rcs = finfo->rcs; ret = NULL; pr = &ret; for (r = revlist; r != NULL; r = r->next) *************** *** 1047,1053 **** nr = xmalloc (sizeof *nr); nr->inclusive = r->inclusive; ! if (r->first == NULL && r->last == NULL) { /* If both first and last are NULL, it means that we want just the head of the default branch, which is RCS_head. */ --- 1049,1076 ---- nr = xmalloc (sizeof *nr); nr->inclusive = r->inclusive; ! if (RCS_is_relative (r->first)) { ! first = Version_resolve_relTag (finfo, r->first, !is_rlog); ! if (!first) ! { ! if (!really_quiet) ! error (0, 0, "Cannot resolve relative tag: `%s'.", r->first); ! } ! } else { ! first = xstrdup (r->first); ! } ! if (RCS_is_relative (r->last)) { ! last = Version_resolve_relTag (finfo, r->last, !is_rlog); ! if (!last && first) ! { ! if (!really_quiet) ! error (0, 0, "Cannot resolve relative tag: `%s'.", r->last); ! } ! } else { ! last = xstrdup (r->last); ! } ! ! if (first == NULL && last == NULL) { /* If both first and last are NULL, it means that we want just the head of the default branch, which is RCS_head. */ *************** *** 1071,1089 **** char *branch; /* Print just the head of the branch. */ ! if (isdigit ((unsigned char) r->first[0])) ! nr->first = RCS_getbranch (rcs, r->first, 1); ! else ! { ! branch = RCS_whatbranch (rcs, r->first); ! if (branch == NULL) ! nr->first = NULL; ! else ! { ! nr->first = RCS_getbranch (rcs, branch, 1); ! free (branch); ! } ! } if (!nr->first) { if (!really_quiet) --- 1094,1113 ---- char *branch; /* Print just the head of the branch. */ ! if (!RCS_is_symbolic (first)) ! nr->first = RCS_getbranch (rcs, first, 1); ! else ! { ! branch = RCS_whatbranch (rcs, first); ! if (branch == NULL) ! nr->first = NULL; ! else ! { ! nr->first = RCS_getbranch (rcs, branch, 1); ! free (branch); ! } ! } ! if (!nr->first) { if (!really_quiet) *************** *** 1100,1115 **** } else { ! if (r->first == NULL || isdigit ((unsigned char) r->first[0])) ! nr->first = xstrdup (r->first); else { ! if (baserev && strcmp (r->first, TAG_BASE) == 0) nr->first = xstrdup (baserev); ! else if (RCS_nodeisbranch (rcs, r->first)) ! nr->first = RCS_whatbranch (rcs, r->first); else ! nr->first = RCS_gettag (rcs, r->first, 1, NULL); if (nr->first == NULL && !really_quiet) { error (0, 0, "warning: no revision `%s' in `%s'", --- 1124,1139 ---- } else { ! if (first == NULL || !RCS_is_symbolic (first)) ! nr->first = xstrdup (first); else { ! if (baserev && strcmp (first, TAG_BASE) == 0) nr->first = xstrdup (baserev); ! else if (RCS_nodeisbranch (rcs, first)) ! nr->first = RCS_whatbranch (rcs, first); else ! nr->first = RCS_gettag (rcs, first, 1, NULL); if (nr->first == NULL && !really_quiet) { error (0, 0, "warning: no revision `%s' in `%s'", *************** *** 1120,1135 **** if (r->last == r->first || (r->last != NULL && r->first != NULL && strcmp (r->last, r->first) == 0)) nr->last = xstrdup (nr->first); ! else if (r->last == NULL || isdigit ((unsigned char) r->last[0])) ! nr->last = xstrdup (r->last); else { ! if (baserev && strcmp (r->last, TAG_BASE) == 0) nr->last = xstrdup (baserev); ! else if (RCS_nodeisbranch (rcs, r->last)) ! nr->last = RCS_whatbranch (rcs, r->last); else ! nr->last = RCS_gettag (rcs, r->last, 1, NULL); if (nr->last == NULL && !really_quiet) { error (0, 0, "warning: no revision `%s' in `%s'", --- 1144,1159 ---- if (r->last == r->first || (r->last != NULL && r->first != NULL && strcmp (r->last, r->first) == 0)) nr->last = xstrdup (nr->first); ! else if (last == NULL || !RCS_is_symbolic (last)) ! nr->last = xstrdup (last); else { ! if (baserev && strcmp (last, TAG_BASE) == 0) nr->last = xstrdup (baserev); ! else if (RCS_nodeisbranch (rcs, last)) ! nr->last = RCS_whatbranch (rcs, last); else ! nr->last = RCS_gettag (rcs, last, 1, NULL); if (nr->last == NULL && !really_quiet) { error (0, 0, "warning: no revision `%s' in `%s'", *************** *** 1141,1147 **** does. This code is a bit cryptic for my tastes, but keeping the same implementation as rlog ensures a certain degree of compatibility. */ ! if (r->first == NULL && nr->last != NULL) { nr->fields = numdots (nr->last) + 1; if (nr->fields < 2) --- 1165,1171 ---- does. This code is a bit cryptic for my tastes, but keeping the same implementation as rlog ensures a certain degree of compatibility. */ ! if (first == NULL && nr->last != NULL) { nr->fields = numdots (nr->last) + 1; if (nr->fields < 2) *************** *** 1156,1162 **** strcpy (cp + 1, "0"); } } ! else if (r->last == NULL && nr->first != NULL) { nr->fields = numdots (nr->first) + 1; nr->last = xstrdup (nr->first); --- 1180,1186 ---- strcpy (cp + 1, "0"); } } ! else if (last == NULL && nr->first != NULL) { nr->fields = numdots (nr->first) + 1; nr->last = xstrdup (nr->first); *************** *** 1278,1283 **** --- 1302,1309 ---- *pr = nr; } + free (first); + free (last); return ret; } Index: home/ortal/ccvs/src/logmsg.c diff -c home/ortal/ccvs/src/logmsg.c:1.3.2.3 home/ortal/ccvs/src/logmsg.c:1.9 *** home/ortal/ccvs/src/logmsg.c:1.3.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/logmsg.c Thu Jun 7 09:46:38 2007 *************** *** 264,269 **** --- 264,288 ---- } } + /* CVS default template for editor is a bunch of lines starting with CVS. + * we would like to have an empty line at the top, but we dont want to do + * this in rcstemplate, as this will force everyone to check-out fresh CVS + * trees in order for this to work. (this may not be so bad in the end, if + * we set RCS template to it, and everyone who will really wants this empty + * line will replace their trees, then gradually the rest will be replaced.) + * + * In order to solve this issue, we tried to add a feature in the config + * file that will tell CVS to add the clear line. However, config is on the + * server side and the editor on the client side, so it does not open the + * config file. we will work in the meantime without the empty line, until + * we think of a way to resolve this issue. + * + * if needed, hard-code it like this with + * #ifdef LOG_MSG_JUNGO + * (void) fprintf (fp, "\n"); + * #endif + */ + (void) fprintf (fp, "%s----------------------------------------------------------------------\n", CVSEDITPREFIX); *************** *** 643,648 **** --- 662,671 ---- li = p->data; arg = li->rev_new ? li->rev_new : "NONE"; break; + case 't': + li = p->data; + arg = li->tag ? li->tag : "NONE"; + break; default: #ifdef SUPPORT_OLD_INFO_FMT_STRINGS if (c->onearg) Index: home/ortal/ccvs/src/ls.c diff -c home/ortal/ccvs/src/ls.c:1.1.2.1 home/ortal/ccvs/src/ls.c:1.2 *** home/ortal/ccvs/src/ls.c:1.1.2.1 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/ls.c Thu Jun 7 09:46:38 2007 *************** *** 460,465 **** --- 460,466 ---- parent[strlen (update_dir) - strlen (dir)] = '\0'; strip_trailing_slashes (parent); p = findnode (callerdat, parent); + free(parent); } else p = NULL; Index: home/ortal/ccvs/src/main.c diff -c home/ortal/ccvs/src/main.c:1.2.2.3 home/ortal/ccvs/src/main.c:1.12 *** home/ortal/ccvs/src/main.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/main.c Thu Jun 7 09:46:38 2007 *************** *** 24,29 **** --- 24,31 ---- #include "strftime.h" #include "xgethostname.h" + #define GDB_DEBUG_ENV "CVS_GDB_DEBUG" + const char *program_name; const char *program_path; const char *cvs_cmd_name; *************** *** 51,57 **** *** CVSROOT/config options *** ***/ ! struct config *config; --- 53,59 ---- *** CVSROOT/config options *** ***/ ! struct config *config = NULL; *************** *** 99,104 **** --- 101,122 ---- } + /* should 'cvs import' be disabled, due to its invalid logic */ + int disable_import = 0; + /* should 'cvs status' show the sticky module name */ + int status_show_module = 0; + /* when adding a file on trunk, should a dead 1.1 revision be added? */ + int create_trunk_dead_rev = 0; + /* when adding a file on a branch, should BASE (1.1) revision be used or + * HEAD (example 1.14)? */ + int branch_from_base_rev = 0; + /* should merge binary identical files? */ + int merge_binary_identical = 0; + /* should merge add operation to an existing file? */ + int merge_add_to_nondead = 0; + /* should commit message show version of dead revision when file is removed? */ + int commit_show_deleted_ver = 0; + /* When our working directory contains subdirectories with different values in CVS/Root files, we maintain a list of them. */ *************** *** 511,517 **** int help = 0; /* Has the user asked for help? This lets us support the `cvs -H cmd' convention to give help for cmd. */ ! static const char short_options[] = "+QqrwtnRvb:T:e:d:Hfz:s:xa"; static struct option long_options[] = { {"help", 0, NULL, 'H'}, --- 529,535 ---- int help = 0; /* Has the user asked for help? This lets us support the `cvs -H cmd' convention to give help for cmd. */ ! static const char short_options[] = "+QqrwtnRvb:T:e:d:Hfz:s:xal"; static struct option long_options[] = { {"help", 0, NULL, 'H'}, *************** *** 558,563 **** --- 576,586 ---- program_name = last_component (argv[0]); #endif + /* debug with gdb */ + cp = getenv (GDB_DEBUG_ENV); + if ((cp = getenv (GDB_DEBUG_ENV)) != NULL) + sleep(20); + /* * Query the environment variables up-front, so that * they can be overridden by command line arguments *************** *** 753,758 **** --- 776,784 ---- We will issue an error later if stream authentication is not supported. */ break; + case 'l': + /* the `-l' option is obsolete - but we need it for tkcvs */ + break; case '?': default: usage (usg); *************** *** 1174,1179 **** --- 1200,1207 ---- } /* end of stuff that gets done if the user DOESN'T ask for help */ root_allow_free (); + + if (config && !server_active) free_config (config); /* This is exit rather than return because apparently that keeps some tools which check for memory leaks happier. */ Index: home/ortal/ccvs/src/mkmodules.c diff -c home/ortal/ccvs/src/mkmodules.c:1.2.2.3 home/ortal/ccvs/src/mkmodules.c:1.8 *** home/ortal/ccvs/src/mkmodules.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/mkmodules.c Wed Jun 13 17:05:39 2007 *************** *** 596,601 **** --- 596,660 ---- "# For example:\n", "#\n", "# UseArchiveCommentLeader=no\n", + "\n", + "# set `DisableImport' to `yes' to disable the `cvs import' command.\n", + "# the logic of `cvs import' is incorrect, and `jcvs import' should be used\n", + "# instead.\n", + "#DisableImport=yes\n", + "\n", + "# set `StatusShowModule' to `yes' to display the sticky module name on\n", + "# `cvs status'\n", + "#StatusShowModule=yes\n", + "\n", + "# set `CreateTrunkDeadRev' to `yes' to create a dead 1.1 revision when\n", + "# adding a file to the trunk. In this case: 1.1 - dead, 1.2 exp.\n", + "# `CreateTrunkDeadRev=yes' also implies `BranchFromBaseRev=yes'.\n", + "#CreateTrunkDeadRev=yes\n", + "\n", + "# set `BranchFromBaseRev' to `yes' to use BASE revision (1.1)\n", + "# instead of using HEAD revision. In this case: 1.1.0.2 instead of\n", + "# 1.7.0.2 will be created.\n", + "#BranchFromBaseRev=yes\n", + "\n", + "# set `MergeBinaryIdentical' to `yes' to perform merge of binary files\n", + "# when one of the merge-from or merge-to revisions is identical\n", + "#MergeBinaryIdentical=yes\n", + "\n", + "# set `MergeAddToNonDead' to `yes' to merge add operations to a\n", + "# non-dead revision.\n", + "#MergeAddToNonDead=yes\n", + "\n", + "# set `CommitShowDeletedVer' to `yes' to display version number\n" + "# of dead revision in the commit message when removing a file.\n" + "# instead of 'new revision: delete;', " + "# it will be 'new revision: delete 1.6;' ", + "#CommitShowDeletedVer=yes\n", + "\n", + NULL + }; + + static const char *const stags_contents[] = { + "# This file holds the list of soft tags.\n", + "#\n", + "# Acceptable formats:\n", + "# T TAG ONBRANCH:ONDATE REPOSITORY\n", + "# T TAG ONTAG REPOSITORY\n", + "# B BRANCH ONBRANCH:ONDATE REPOSITORY\n", + "# B BRANCH ONTAG REPOSITORY\n", + "# params:\n", + "# 'T': soft-tag definition\n", + "# 'B': soft-branch definition\n", + "# TAG/BRANCH: declares the name of the soft-tag/soft-branch\n", + "# ONBRANCH:\n", + "# For tags: the name of the branch this tag is on.\n", + "# For branches: the name of the parent branch (the branching point).\n", + "# ONDATE: the date in RCS format (YYYY.MM.DD.HH.MM.SS)\n", + "# For tags: the date of the tag on the branch (ONBRANCH).\n", + "# For branches: the date of the branching point from the parent branch (ONBRNACH).\n", + "# ONTAG:\n", + "# For tags: an alias ('T tag2 tag1' means tag2 equals tag1).\n", + "# For branches: the tag of the branching point (branch start location).\n", + "# REPOSITORY: the location in the repository where the tag is valid.\n", NULL }; *************** *** 673,678 **** --- 732,740 ---- {CVSROOTADM_CONFIG, "a %s file configures various behaviors", config_contents}, + {CVSROOTADM_STAGS, + "a %s file stores details of soft tags", + stags_contents}, {NULL, NULL, NULL} }; Index: home/ortal/ccvs/src/modules.c diff -c home/ortal/ccvs/src/modules.c:1.3.2.3 home/ortal/ccvs/src/modules.c:1.9 *** home/ortal/ccvs/src/modules.c:1.3.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/modules.c Thu Jun 7 09:46:38 2007 *************** *** 157,163 **** --- 157,173 ---- /* if this is a directory to ignore, add it to that list */ if (mname[0] == '!' && mname[1] != '\0') { + #ifdef STICKY_MODULES + char *file = xmalloc (strlen (current_parsed_root->directory) + + strlen (mname) + 1); + (void) sprintf (file, "%s/%s", current_parsed_root->directory, + mname + 1); + + ign_dir_add (file); + free(file); + #else ign_dir_add (mname+1); + #endif goto do_module_return; } Index: home/ortal/ccvs/src/parseinfo.c diff -c home/ortal/ccvs/src/parseinfo.c:1.2.2.3 home/ortal/ccvs/src/parseinfo.c:1.10 *** home/ortal/ccvs/src/parseinfo.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/parseinfo.c Thu Jun 7 09:46:38 2007 *************** *** 315,320 **** --- 315,326 ---- free_config (struct config *data) { if (data->keywords) free_keywords (data->keywords); + if (data->logHistory) free (data->logHistory); + if (data->HistorySearchPath) free (data->HistorySearchPath); + if (data->UserAdminOptions) free (data->UserAdminOptions); + if (data->HistoryLogPath) free (data->HistoryLogPath); + if (data->lock_dir) free(data->lock_dir); + if (data->TmpDir) free(data->TmpDir); free (data); } *************** *** 696,701 **** --- 702,740 ---- readSizeT (infopath, "MaxCompressionLevel", p, &retval->MaxCompressionLevel); #endif /* SERVER_SUPPORT */ + else if (!strcmp (line, "DisableImport") || + !strcmp(line, "StatusShowModule") || + !strcmp(line, "CreateTrunkDeadRev") || + !strcmp(line, "BranchFromBaseRev") || + !strcmp(line, "MergeBinaryIdentical") || + !strcmp(line, "MergeAddToNonDead") || + !strcmp(line, "CommitShowDeletedVer")) + { + int *param = NULL; + if (!strcmp(line, "DisableImport")) + param = &disable_import; + else if (!strcmp(line, "CreateTrunkDeadRev")) + param = &create_trunk_dead_rev; + else if (!strcmp(line, "BranchFromBaseRev")) + param = &branch_from_base_rev; + else if (!strcmp(line, "MergeBinaryIdentical")) + param = &merge_binary_identical; + else if (!strcmp(line, "StatusShowModule")) + param = &status_show_module; + else if (!strcmp(line, "MergeAddToNonDead")) + param = &merge_add_to_nondead; + else if (!strcmp(line, "CommitShowDeletedVer")) + param = &commit_show_deleted_ver; + if (!strcmp(p, "yes")) + *param = 1; + else if (!strcmp(p, "no")) + *param = 0; + else + { + error (0, 0, "unrecognized value '%s' for %s", p, line); + break; + } + } else /* We may be dealing with a keyword which was added in a subsequent version of CVS. In that case it is a good idea Index: home/ortal/ccvs/src/patch.c diff -c home/ortal/ccvs/src/patch.c:1.2.2.3 home/ortal/ccvs/src/patch.c:1.6 *** home/ortal/ccvs/src/patch.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/patch.c Sun Jun 10 10:40:34 2007 *************** *** 394,399 **** --- 394,400 ---- int dargc = 0; size_t darg_allocated = 0; char **dargv = NULL; + Vers_TS *vers; line1 = NULL; line1_chars_allocated = 0; *************** *** 417,424 **** vers_head = NULL; else { ! vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match, ! NULL); if (vers_head != NULL && RCS_isdead (rcsfile, vers_head)) { free (vers_head); --- 418,428 ---- vers_head = NULL; else { ! vers = Version_TS (finfo, NULL, rev2, date2, force_tag_match, 0); ! if (vers->vn_rcs != NULL) ! vers_head = xstrdup (vers->vn_rcs); ! freevers_ts (&vers); ! if (vers_head != NULL && RCS_isdead (rcsfile, vers_head)) { free (vers_head); *************** *** 446,452 **** goto out2; } } ! vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match, NULL); if (vers_tag != NULL && RCS_isdead (rcsfile, vers_tag)) { free (vers_tag); --- 450,459 ---- goto out2; } } ! vers = Version_TS (finfo, NULL, rev1, date1, force_tag_match, 0); ! if (vers->vn_rcs != NULL) ! vers_tag = xstrdup (vers->vn_rcs); ! freevers_ts (&vers); if (vers_tag != NULL && RCS_isdead (rcsfile, vers_tag)) { free (vers_tag); Index: home/ortal/ccvs/src/rcs.c diff -c home/ortal/ccvs/src/rcs.c:1.2.2.3 home/ortal/ccvs/src/rcs.c:1.14 *** home/ortal/ccvs/src/rcs.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/rcs.c Sun Jul 8 19:22:58 2007 *************** *** 69,74 **** --- 69,76 ---- }; static RCSNode *RCS_parsercsfile_i (FILE * fp, const char *rcsfile); + static char *RCS_getdatetrunk (RCSNode * rcs, const char *date, + int force_tag_match); static char *RCS_getdatebranch (RCSNode * rcs, const char *date, const char *branch); static void rcsbuf_open (struct rcsbuffer *, FILE *fp, *************** *** 98,106 **** static void free_rcsnode_contents (RCSNode *); static void free_rcsvers_contents (RCSVers *); static void rcsvers_delproc (Node * p); static char *translate_symtag (RCSNode *, const char *); static char *RCS_addbranch (RCSNode *, const char *); - static char *truncate_revnum_in_place (char *); static char *truncate_revnum (const char *); static char *printable_date (const char *); static char *escape_keyword_value (const char *, int *); --- 100,113 ---- static void free_rcsnode_contents (RCSNode *); static void free_rcsvers_contents (RCSVers *); static void rcsvers_delproc (Node * p); + static char *RCS_getroot (RCSNode *, const char *); + static char *RCS_getprevious (RCSNode *, const char *); + static char *RCS_getnext (RCSNode *, const char *); + static char *RCS_getorigin (RCSNode *, const char *); + static char *RCS_getcommitid (RCSNode *, const char *, bool); + static char *translate_tag (RCSNode *rcs, const char *, bool); static char *translate_symtag (RCSNode *, const char *); static char *RCS_addbranch (RCSNode *, const char *); static char *truncate_revnum (const char *); static char *printable_date (const char *); static char *escape_keyword_value (const char *, int *); *************** *** 129,134 **** --- 136,146 ---- static void rcs_internal_unlockfile (FILE *, char *); static char *rcs_lockfilename (const char *); + static char * + RCS_locate_softtag_and_date (RCSNode *rcs, const char *tag, const char *date); + char * + RCS_getsofttag (RCSNode *rcs, const char *tag, bool lookup, bool force); + /* The RCS file reading functions are called a lot, and they do some string comparisons. This macro speeds things up a bit by skipping the function call when the first characters are different. It *************** *** 169,176 **** static char *rcs_lockfile = NULL; static int rcs_lockfd = -1; - - /* * char * * locate_rcs ( const char* file, const char *repository , int *inattic ) --- 181,186 ---- *************** *** 2142,2147 **** --- 2152,2205 ---- + /* Return true if TAG does not start with a number or + * does not entirely consist of numbers and dots. + * + * (N.N.N.N.prev is now a valid tag). + */ + static inline bool + is_symbolic (const char *tag) + { + assert (tag && *tag); + if (!isdigit (*tag)) return true; + for (tag++; *tag; tag++) + if (!(isdigit (*tag) || *tag == '.')) return true; + if (*--tag == '.') return true; + return false; + } + + bool + RCS_is_symbolic (const char *tag) + { + return is_symbolic (tag); + } + + bool + RCS_is_relative (const char *tag) + { + if (tag && *tag == '.') + { + int len; + char *next; + if (++tag) + { + next = strchr (tag, '.'); + if (next) + len = next - tag; + else + len = strlen (tag); + if (!strncmp (tag, TAG_DOTHEAD, len) + || !strncmp (tag, TAG_DOTBASE, len) + || !strncmp (tag, TAG_PREVIOUS, len) + || !strncmp (tag, TAG_NEXT, len) + || !strncmp (tag, TAG_ROOT, len) + || !strncmp (tag, TAG_ORIGIN, len)) + return true; + } + } + return false; + } + /* * Version Number * *************** *** 2164,2184 **** { char *branch, *rev; if (! RCS_nodeisbranch (rcs, tag)) { /* We can't get a particular date if the tag is not a ! branch. */ return NULL; } /* Work out the branch. */ ! if (! isdigit ((unsigned char) tag[0])) branch = RCS_whatbranch (rcs, tag); else branch = xstrdup (tag); /* Fetch the revision of branch as of date. */ ! rev = RCS_getdatebranch (rcs, date, branch); free (branch); return rev; } --- 2222,2251 ---- { char *branch, *rev; + if (tag_is_soft(rcs, tag, 0)) + return RCS_locate_softtag_and_date (rcs, tag, date); + if (! RCS_nodeisbranch (rcs, tag)) { /* We can't get a particular date if the tag is not a ! branch. */ return NULL; } /* Work out the branch. */ ! if (is_symbolic (tag)) branch = RCS_whatbranch (rcs, tag); else branch = xstrdup (tag); + int dots = numdots (branch); + /* Fetch the revision of branch as of date. */ ! if (!dots) ! rev = RCS_getdatetrunk (rcs, date, force_tag_match); ! else ! rev = RCS_getdatebranch (rcs, date, branch); ! free (branch); return rev; } *************** *** 2201,2206 **** --- 2268,2275 ---- * returns the magic branch number. * -- If tag is a branch tag, returns the branch number, not * the revision of the head of the branch. + * -- An exception is made for '.trunk' as it returns the + * head revision of the trunk * If tag or revision is not valid or does not exist in file, * return NULL. */ *************** *** 2271,2291 **** error (1, 0, "revision `%s' does not exist", tag); } - - RCS_check_tag (tag); /* exit if not a valid tag */ - /* If tag is "HEAD", special case to get head RCS revision */ if (tag && STREQ (tag, TAG_HEAD)) return RCS_head (rcs); ! /* If valid tag let translate_symtag say yea or nay. */ ! rev = translate_symtag (rcs, tag); ! if (rev) ! return rev; /* Trust the caller to print warnings. */ ! return NULL; } --- 2340,2358 ---- error (1, 0, "revision `%s' does not exist", tag); } /* If tag is "HEAD", special case to get head RCS revision */ if (tag && STREQ (tag, TAG_HEAD)) return RCS_head (rcs); ! /* If valid tag let RCS_extract_tag say yea or nay. */ ! char *tmp = RCS_extract_tag (tag, true); ! if (tmp) free (tmp); ! /* We need to preserve magic branch numbers here */ ! rev = translate_tag (rcs, tag, true); /* Trust the caller to print warnings. */ ! return rev; } *************** *** 2325,2374 **** #endif return RCS_head (rcs); ! if (!isdigit ((unsigned char) symtag[0])) { char *version; ! /* If we got a symbolic tag, resolve it to a numeric */ ! version = translate_symtag (rcs, symtag); ! if (version != NULL) { int dots; - char *magic, *branch, *cp; - tag = version; /* ! * If this is a magic revision, we turn it into either its * physical branch equivalent (if one exists) or into * its base revision, which we assume exists. */ dots = numdots (tag); ! if (dots > 2 && (dots & 1) != 0) { ! branch = strrchr (tag, '.'); ! cp = branch++ - 1; ! while (*cp != '.') ! cp--; ! ! /* see if we have .magic-branch. (".0.") */ ! magic = xmalloc (strlen (tag) + 1); ! (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH); ! if (strncmp (magic, cp, strlen (magic)) == 0) ! { ! /* it's magic. See if the branch exists */ ! *cp = '\0'; /* turn it into a revision */ ! (void) sprintf (magic, "%s.%s", tag, branch); ! branch = RCS_getbranch (rcs, magic, 1); ! free (magic); ! if (branch != NULL) ! { ! free (tag); ! return branch; ! } ! return tag; } ! free (magic); } } else --- 2392,2424 ---- #endif return RCS_head (rcs); ! if (is_symbolic (symtag)) { char *version; ! /* Resolve to a numeric revision number */ ! version = translate_tag (rcs, symtag, false); ! if (version) { int dots; tag = version; /* ! * If this is a branch tag, we turn it into either its * physical branch equivalent (if one exists) or into * its base revision, which we assume exists. */ dots = numdots (tag); ! if (dots && !(dots & 1)) { ! version = RCS_getbranch (rcs, tag, 1); ! if (version != NULL) ! { ! free (tag); ! return version; } ! *strrchr (tag, '.') = '\0'; ! return tag; } } else *************** *** 2527,2540 **** * or symbolic tag resolves to a "branch" within the rcs file. * * FIXME: this is the same as RCS_nodeisbranch except for the special ! * case for handling a null rcsnode. */ int RCS_isbranch (RCSNode *rcs, const char *rev) { ! /* numeric revisions are easy -- even number of dots is a branch */ if (isdigit ((unsigned char) *rev)) return (numdots (rev) & 1) == 0; /* assume a revision if you can't find the RCS info */ if (rcs == NULL) --- 2577,2598 ---- * or symbolic tag resolves to a "branch" within the rcs file. * * FIXME: this is the same as RCS_nodeisbranch except for the special ! * case for handling a null rcsnode and numeric magic branches. */ int RCS_isbranch (RCSNode *rcs, const char *rev) { ! Soft_Tag *soft_tag; ! ! /* numeric revisions are easy -- even number of dots is a branch ! * Note that magic branch numbers are not checked ! */ if (isdigit ((unsigned char) *rev)) return (numdots (rev) & 1) == 0; + + soft_tag = tag_is_soft(rcs, rev, 0); + if (soft_tag) + return soft_tag->is_branch; /* assume a revision if you can't find the RCS info */ if (rcs == NULL) *************** *** 2548,2647 **** /* * Given an RCSNode, returns non-zero if the specified revision number ! * or symbolic tag resolves to a "branch" within the rcs file. We do * take into account any magic branches as well. */ ! int ! RCS_nodeisbranch (RCSNode *rcs, const char *rev) { int dots; char *version; ! assert (rcs != NULL); ! ! /* numeric revisions are easy -- even number of dots is a branch */ ! if (isdigit ((unsigned char) *rev)) ! return (numdots (rev) & 1) == 0; ! ! version = translate_symtag (rcs, rev); ! if (version == NULL) ! return 0; ! dots = numdots (version); ! if ((dots & 1) == 0) ! { ! free (version); ! return 1; ! } ! /* got a symbolic tag match, but it's not a branch; see if it's magic */ ! if (dots > 2) { ! char *magic; ! char *branch = strrchr (version, '.'); ! char *cp = branch - 1; ! while (*cp != '.') ! cp--; ! ! /* see if we have .magic-branch. (".0.") */ ! magic = Xasprintf (".%d.", RCS_MAGIC_BRANCH); ! if (strncmp (magic, cp, strlen (magic)) == 0) { free (magic); - free (version); - return 1; } ! free (magic); } free (version); ! return 0; } ! /* ! * Returns a pointer to malloc'ed memory which contains the branch ! * for the specified *symbolic* tag. Magic branches are handled correctly. */ char * ! RCS_whatbranch (RCSNode *rcs, const char *rev) { char *version; int dots; ! /* assume no branch if you can't find the RCS info */ ! if (rcs == NULL) ! return NULL; ! /* now, look for a match in the symbols list */ ! version = translate_symtag (rcs, rev); ! if (version == NULL) ! return NULL; ! dots = numdots (version); ! if ((dots & 1) == 0) ! return version; ! /* got a symbolic tag match, but it's not a branch; see if it's magic */ ! if (dots > 2) { ! char *magic; ! char *branch = strrchr (version, '.'); ! char *cp = branch++ - 1; ! while (*cp != '.') ! cp--; ! ! /* see if we have .magic-branch. (".0.") */ ! magic = xmalloc (strlen (version) + 1); ! (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH); ! if (strncmp (magic, cp, strlen (magic)) == 0) ! { ! /* yep. it's magic. now, construct the real branch */ ! *cp = '\0'; /* turn it into a revision */ ! (void) sprintf (magic, "%s.%s", version, branch); ! free (version); ! return magic; } - free (magic); } free (version); return NULL; } --- 2606,2722 ---- /* * Given an RCSNode, returns non-zero if the specified revision number ! * or symbolic TAG resolves to a "branch" within the rcs file. We do * take into account any magic branches as well. + * + * NOTES + * Resolves TAG when it is symbolic but does not verify existance of + * revisions. */ ! bool ! RCS_nodeisbranch (RCSNode *rcs, const char *tag) { int dots; char *version; + Soft_Tag *soft_tag; ! assert (rcs); ! /* numeric revisions are easy -- even number of dots is a branch ! * Note that we need to care about magic branch numbers ! */ ! if (!is_symbolic (tag)) { ! dots = numdots (tag); ! if (dots > 1) { + char *magic; + char *p = strrchr (tag, '.') - 1; + while (*p != '.') --p; + magic = Xasprintf (".%d.", RCS_MAGIC_BRANCH); + if (!strncmp (p, magic, strlen (magic))) + { + free (magic); + return (dots & 1); + } free (magic); } ! return !(dots & 1); } + + soft_tag = tag_is_soft(rcs, tag, 0); + if (soft_tag) + return soft_tag->is_branch; + + /* resolve to its numeric equivalent and remove magic */ + version = translate_tag (rcs, tag, false); + + if (!version) return false; + + dots = numdots (version); free (version); ! ! if (!(dots & 1)) ! return true; ! ! return false; } ! /* Returns a pointer to malloc'ed memory which contains the branch ! * for the specified, and possibly symbolic, TAG. Magic branches are handled ! * correctly. */ char * ! RCS_whatbranch (RCSNode *rcs, const char *tag) { char *version; int dots; ! assert (tag); ! /* assume no branch if you can't find the RCS info */ ! if (!rcs) return NULL; ! if (is_symbolic (tag)) { ! /* now, look for a match in the symbols list */ ! version = translate_tag (rcs, tag, false); ! if (!version) return NULL; ! dots = numdots (version); ! } ! else ! { ! version = xstrdup (tag); ! dots = numdots (version); ! ! if (dots > 2 && (dots & 1)) ! { ! /* See if it's magic; Convert into physical equivalent if so */ ! char *magic; ! char *branch = strrchr (version, '.'); ! char *p = branch++ - 1; ! while (*p != '.') --p; ! ! /* see if we have .magic-branch. (".0.") */ ! magic = Xasprintf (".%d.", RCS_MAGIC_BRANCH); ! if (!strncmp (p, magic, strlen (magic))) ! { ! /* It's magic! Construct the real branch */ ! free (magic); ! *p = '\0'; /* turn it into a revision */ ! magic = Xasprintf ("%s.%s", version, branch); ! free (version); ! return magic; ! } ! free (magic); } } + + if (!(dots & 1)) + return version; + free (version); return NULL; } *************** *** 2763,2796 **** ! /* Returns the head of the branch which REV is on. REV can be a ! branch tag or non-branch tag; symbolic or numeric. ! Returns a newly malloc'd string. Returns NULL if a symbolic name ! isn't found. */ char * ! RCS_branch_head (RCSNode *rcs, char *rev) { char *num; - char *br; char *retval; ! assert (rcs != NULL); ! ! if (RCS_nodeisbranch (rcs, rev)) ! return RCS_getbranch (rcs, rev, 1); ! if (isdigit ((unsigned char) *rev)) ! num = xstrdup (rev); ! else { ! num = translate_symtag (rcs, rev); ! if (num == NULL) ! return NULL; } ! br = truncate_revnum (num); ! retval = RCS_getbranch (rcs, br, 1); ! free (br); free (num); return retval; } --- 2838,2886 ---- ! /* Revision number string, R, must contain a `.'. ! * R must be writable. Replace the rightmost `.' in R with ! * the NUL byte and return a pointer to that NUL byte. ! */ ! static inline char * ! truncate_revnum_in_place (char *r) ! { ! char *dot = strrchr (r, '.'); ! assert (dot); ! *dot = '\0'; ! return dot; ! } ! ! ! /* Returns the head of the branch which the possibly symbolic TAG is on. ! * TAG can be a branch tag or non-branch tag; symbolic or numeric. ! * ! * Returns a newly malloc'd string. Returns NULL if a symbolic name ! * isn't found. ! */ char * ! RCS_branch_head (RCSNode *rcs, const char *tag) { char *num; char *retval; ! assert (rcs && tag); ! if (is_symbolic (tag)) { ! num = translate_tag (rcs, tag, false); ! if (!num) return NULL; } ! else ! /* FIXME: Validate revnum? */ ! num = xstrdup (tag); ! ! if (!RCS_nodeisbranch (rcs, num)) ! /* Make NUM = NUM's branch. */ ! truncate_revnum_in_place (num); ! ! retval = RCS_getbranch (rcs, num, 1); free (num); return retval; } *************** *** 2883,2894 **** * rcs The parsed rcs node information. * * RETURNS ! * NULL when rcs->branch exists and cannot be found. * A newly malloc'd string, otherwise. */ char * RCS_head (RCSNode *rcs) { /* make sure we have something to look at... */ assert (rcs); --- 2973,2988 ---- * rcs The parsed rcs node information. * * RETURNS ! * NULL when rcs->branch exists and cannot be found or when there are no ! * revisions in the RCS file. ! * * A newly malloc'd string, otherwise. */ char * RCS_head (RCSNode *rcs) { + char *retval; + /* make sure we have something to look at... */ assert (rcs); *************** *** 2898,2905 **** */ if (rcs->branch) return RCS_getbranch (rcs, rcs->branch, 1); ! else ! return xstrdup (rcs->head); } --- 2992,3009 ---- */ if (rcs->branch) return RCS_getbranch (rcs, rcs->branch, 1); ! ! retval = xstrdup (rcs->head); ! if (!retval) return NULL; ! ! if (!(numdots (retval) & 1)) ! { ! error (0, 0, "Head revision is a branch in `%s'.", rcs->path); ! free (retval); ! return NULL; ! } ! ! return retval; } *************** *** 2930,2936 **** return retval; } ! /* otherwise if we have a trunk, try it */ if (rcs->head) { p = findnode (rcs->versions, rcs->head); --- 3034,3062 ---- return retval; } ! /* otherwise if we have a trunk, use it */ ! return RCS_getdatetrunk (rcs, date, force_tag_match); ! } ! ! ! ! /* ! * Look up the last element on the trunk that was put in before or on ! * the specified date and time (return the rev or NULL) ! * Follow the vendor branch if not found on the trunk ! */ ! static char * ! RCS_getdatetrunk (RCSNode *rcs, const char *date, int force_tag_match) ! { ! Node *p = NULL; ! RCSVers *vers = NULL; ! char *retval = NULL; ! ! assert(rcs); ! ! if (rcs->flags & PARTIAL) ! RCS_reparsercsfile (rcs, NULL, NULL); ! if (rcs->head) { p = findnode (rcs->versions, rcs->head); *************** *** 2945,2952 **** vers = p->data; if (RCS_datecmp (vers->date, date) <= 0) { ! cur_rev = vers->version; ! break; } /* if there is a next version, find the node */ --- 3071,3078 ---- vers = p->data; if (RCS_datecmp (vers->date, date) <= 0) { ! retval = vers->version; ! break; } /* if there is a next version, find the node */ *************** *** 2966,2975 **** */ /* if we found what we're looking for, and it's not 1.1 return it */ ! if (cur_rev != NULL) { ! if (! STREQ (cur_rev, "1.1")) ! return xstrdup (cur_rev); /* This is 1.1; if the date of 1.1 is not the same as that for the 1.1.1.1 version, then return 1.1. This happens when the first --- 3092,3101 ---- */ /* if we found what we're looking for, and it's not 1.1 return it */ ! if (retval != NULL) { ! if (! STREQ (retval, "1.1")) ! return xstrdup (retval); /* This is 1.1; if the date of 1.1 is not the same as that for the 1.1.1.1 version, then return 1.1. This happens when the first *************** *** 2986,2992 **** } } - /* look on the vendor branch */ retval = RCS_getdatebranch (rcs, date, CVSBRANCH); /* --- 3112,3117 ---- *************** *** 3224,3237 **** /* * Return the version associated with a particular symbolic tag. * Returns NULL or a newly malloc'd string. */ static char * translate_symtag (RCSNode *rcs, const char *tag) { ! if (rcs->flags & PARTIAL) ! RCS_reparsercsfile (rcs, NULL, NULL); if (rcs->symbols != NULL) { --- 3349,4168 ---- /* + * Find the previous revision + * + * RETURN + * Branch: return the HEAD-1 revision or NULL + * Revision: return the previous revision or NULL + * + * ASSUMPTIONS + * The tag is valid, it has been validated by RCS_check_tag + * The Tag does not contain RCS_MAGIC_BRANCH + */ + static char * + RCS_getprevious (RCSNode *rcs, const char *rev) + { + char *retval = NULL; + int dots = numdots (rev); + char *trev = NULL; + + if (!(dots & 1)) /* branch handling => turn into a head revision */ + { + trev = RCS_branch_head (rcs, rev); + if (!trev) + { + /* branch not found, + * so only the tag exists ... take its revision + */ + trev = xstrdup (rev); + truncate_revnum_in_place (trev); + } + dots = numdots (trev); + } + else + trev = xstrdup (rev); + + if (rcs->flags & PARTIAL) + RCS_reparsercsfile (rcs, NULL, NULL); + + if (dots > 1) /* revision on a branch */ + { + /* find the root revision */ + char *p1 = strrchr (trev, '.'); + *p1 = '\0'; + int len = strlen (trev); + char *p2 = strrchr (trev, '.'); + *p2 = '\0'; + + RCSVers *vers = NULL; + Node *node = findnode (rcs->versions, trev); + if (node && (vers = node->data) && vers->branches) + { + *p1 = '.'; + *p2 = '.'; + char *rootdate = vers->date; + Node *head = vers->branches->list; + Node *br; + for (br = head->next; br != head; br = br->next) + { + if (node = findnode (rcs->versions, br->key)) + { + if (strncmp (((RCSVers *)node->data)->version, trev, len)) + continue; + + ++len; + char *p = NULL; + while (node != NULL) + { + vers = node->data; + if (STREQ (vers->version + len, trev + len)) + { + if (p) + retval = xstrdup (p); + else if (RCS_datecmp (vers->date, rootdate)) + { + *p2 = '\0'; + retval = xstrdup (trev); + } + break; + } + + /* if there is a next version, find the node */ + if (vers->next != NULL) + { + p = vers->version; + node = findnode (rcs->versions, vers->next); + } + else + node = NULL; + } + break; + } + } + } + } + else /* revision on trunk */ + { + char *prev = NULL; + char *curdate = NULL; + + assert (dots == 1); + + if (!STREQ (trev, "1.1")) + { + Node *node = findnode (rcs->versions, trev); + if (node) + { + RCSVers *v = node->data; + curdate = v->date; + if (v->next && (node = findnode (rcs->versions, v->next))) + { + free (trev); + prev = ((RCSVers *)node->data)->version; + trev = xstrdup (prev); + } + } + } + + if (prev && STREQ (trev, "1.1")) + { + /* This is 1.1; if the date of 1.1 is the same as that for + * the VENDOR.1 version, then return the latest VENDOR version with + * a timestamp before the 1.2 timestamp (point of merge). The + * date of 1.1. and VENDOR.1 differs if the first version of + * a file is created by a regular cvs add and commit, and there + * is a subsequent cvs import of the same file ==> return 1.1. + * If 1.1 is dead, the file was initially added on a branch + * ==> return NULL. + */ + Node *rootnode = findnode (rcs->versions, trev); + if (rootnode) + { + RCSVers *vers = rootnode->data; + if (!vers->dead && vers->branches) + { + char *date_1_1 = vers->date;//vers 1.1 + + Node *head = vers->branches->list; + Node *br; + for (br = head->next; br != head; br = br->next) + { + Node *node = NULL; + if (node = findnode (rcs->versions, br->key)) + { + vers = node->data; + if (!vers->dead + && !RCS_datecmp (vers->date, date_1_1)) + { + /* get head of branch */ + retval = vers->version; + while (vers->next) + { + node = findnode (rcs->versions, + vers->next); + if (node) + { + vers = node->data; + if (RCS_datecmp (curdate, + vers->date) > 0) + { + vers = node->data; + retval = vers->version; + continue; + } + } + break; + } + retval = xstrdup (retval); + } + } + } + } + } + } + if (!retval && prev) + retval = xstrdup (prev); + } + free (trev); + + return retval; + } + + + + /* + * Find the next revision + * + * RETURN + * Branch: NULL (There cannot be a revision) + * Revision: returns the next revision or NULL + * + * ASSUMPTIONS + * The tag is valid, it has been validated by RCS_check_tag + * The Tag does not contain RCS_MAGIC_BRANCH + */ + static char * + RCS_getnext (RCSNode *rcs, const char *rev) + { + Node *node = NULL; + RCSVers *vers = NULL; + char *retval = NULL; + const char *cmp = rev; + int dots = numdots (rev); + + if (rcs->flags & PARTIAL) + RCS_reparsercsfile (rcs, NULL, NULL); + + if (dots > 1) + { + node = findnode (rcs->versions, rev); + if (!node) + return NULL; + + vers = node->data; + + /* if there is a next version, find the node */ + if (vers->next != NULL) + { + node = findnode (rcs->versions, vers->next); + if (node) + return xstrdup (((RCSVers *)node->data)->version); + } + } + else if (rcs->head) + { + node = findnode (rcs->versions, rcs->head); + if (node) + { + RCSVers *next = NULL; + vers = NULL; + while (node != NULL) + { + vers = next; + next = node->data; + if (next && STREQ (next->version, cmp)) + { + if (vers) + retval = xstrdup (vers->version); + break; + } + + /* if there is a next version, find the node */ + if (next->next != NULL) + node = findnode (rcs->versions, next->next); + else + node = NULL; + } + } + } + + return retval; + } + + + + /* + * Find the origin revision, which is the first revision + * on either the trunk or a branch if added there. + * + * ASSUMPTIONS + * The tag is valid, it has been validated by RCS_check_tag + * The Tag does not contain RCS_MAGIC_BRANCH + */ + static char * + RCS_getorigin (RCSNode *rcs, const char *rev) + { + char *trev; + int dots = numdots (rev); + + if (!(dots & 1)) /* branch handling => turn into a head revision */ + { + trev = RCS_branch_head (rcs, rev); + if (trev) + { + if (dots > (dots = numdots (trev))) + { + /* Got the root revision. The first commit to the branch is + * defined as the origin, so return NULL. + */ + free (trev); + return NULL; + } + /* Else, we have a head revision on the branch. */ + } + else + /* Error - branch not found... */ + return NULL; + } + else + trev = xstrdup (rev); + + assert (dots == numdots (trev)); + + if (RCS_exist_rev (rcs, trev)) + { + Node *rootnode = NULL; + + while (dots > 1) + { + int len; + char *tmp = trev; + trev = xstrdup (tmp); + + truncate_revnum_in_place (trev); + len = strlen (trev); + truncate_revnum_in_place (trev); + + /* If a file was added on the trunk, and it is added on + * a branch in a second step, the '1.1.2.1' revision is + * dead, and timestamp of 1.1 and 1.1.2.1 are equal. + * Prevent returning this as root! + */ + bool found = false; + rootnode = findnode (rcs->versions, trev); + if (rootnode) + { + RCSVers *vers = rootnode->data; + if (vers->branches) + { + Node *head = vers->branches->list; + Node *br; + for (br = head->next; br != head; br = br->next) + { + /* check if br->key is on branch rev */ + if (!strncmp (tmp, br->key, len)) + { + Node *bn = NULL; + if (bn = findnode (rcs->versions, br->key)) + { + RCSVers *cv = bn->data; + if (cv->dead) + { + if (cv->next) + { + free (trev); + if (STREQ (cv->version, rev)) + trev = xstrdup (rev); + else + { + bn = findnode (rcs->versions, + cv->next); + cv = bn->data; + trev = xstrdup (cv->version); + } + found = true; + } + else + { + free (trev); + trev = NULL; + } + } + else if (vers->dead) + { + /* root dead => stay on branch */ + free (trev); + trev = xstrdup (cv->version); + found = true; + } + } + } + } + } + } + if (found || !trev) + return trev; + else + dots = numdots (trev); + free (tmp); + } + + RCSVers *vers; + char *prev = NULL; + + if (!rootnode) + rootnode = findnode (rcs->versions, trev); + free (trev); + + while (rootnode) + { + vers = rootnode->data; + + /* if there is a next version, find the node */ + if (vers->next != NULL) + { + prev = vers->version; + rootnode = findnode (rcs->versions, vers->next); + } + else if (vers->dead) + return xstrdup (prev); + else + return xstrdup (vers->version); + } + } + free (trev); + return NULL; + } + + + + /* + * Find the branchpoint, no matter if rev points + * to a branch or a revision + * + * ASSUMPTIONS + * The tag is valid, it has been validated by RCS_check_tag + * The Tag does not contain RCS_MAGIC_BRANCH + */ + static char * + RCS_getroot (RCSNode *rcs, const char *rev) + { + char *retval = NULL; + RCSVers *vers = NULL; + int dots = numdots (rev); + + if (dots > 1) + { + int len; + retval = xstrdup (rev); + + if (dots & 1) + { + *strrchr (retval, '.') = '\0'; + len = strlen (retval); + *strrchr (retval, '.') = '\0'; + } + else + { + len = strlen (retval); + *strrchr (retval, '.') = '\0'; + } + + /* If a file was added on the trunk, and it is added on + * a branch in a second step, the '1.1.2.1' revision is + * dead, and timestamp of 1.1 and 1.1.2.1 are equal. + * Return 1.1.2.1 in this case! + */ + if (rcs->flags & PARTIAL) + RCS_reparsercsfile (rcs, NULL, NULL); + + Node *node = findnode(rcs->versions, retval); + if (node) + { + vers = node->data; + if (vers->branches) + { + char *rootdate = vers->date; + Node *head = vers->branches->list; + Node *br; + for (br = head->next; br != head; br = br->next) + { + //check if br->key is on branch rev + if (!strncmp (rev, br->key, len)) + { + if (node = findnode (rcs->versions, br->key)) + { + vers = node->data; + if (vers->dead && !RCS_datecmp (rootdate, vers->date)) + { + free (retval); + if (STREQ (vers->version, rev)) + return NULL; + else + return xstrdup (vers->version); + } + } + return retval; + } + } + } + else + { + /* Branch tag exists, but no revisions are on this branch + * Return the revision, it already is the root + */ + return retval; + } + } + free (retval); + } + return NULL; + } + + + + /* + * Find the commitid, if prev is true return the + * previous revision + * If a revisions was initially added on a branch, there will + * be two revision with identical commitid. In this case, + * take the one that's not dead. + */ + static char * + RCS_getcommitid (RCSNode *rcs, const char *commitid, bool prev) + { + Node *p; + RCSVers *oldvers = NULL; + char *result = NULL; + char *cmp = xstrdup (commitid); + + if (rcs->flags & PARTIAL) + RCS_reparsercsfile (rcs, NULL, NULL); + + Node *head = rcs->versions->list; + for (p = head->next; p != head; p = p->next) + { + RCSVers *vers = (RCSVers *)p->data; + + Node *info = findnode (vers->other_delta, "commitid"); + if (info != NULL) + if (!strcmp (info->data, cmp)) + { + RCSVers *next_vers = NULL; + bool maybe_duplicate = false; + if (!prev) + { + if (result) + free (result); + result = xstrdup (vers->version); + maybe_duplicate = vers->dead; + } + else + { + if (p->next) + { + if (numdots (vers->version) == 1) + next_vers = (RCSVers *)p->next->data; + } + else + next_vers = oldvers; + if (next_vers && + (RCS_datecmp (next_vers->date, vers->date) < 0)) + { + result = xstrdup (next_vers->version); + if (next_vers->dead) + { + info = findnode (next_vers->other_delta, "commitid"); + if (info) + { + free (cmp); + cmp = xstrdup (info->data); + maybe_duplicate = true; + prev = false; + } + } + } + else + result = RCS_getprevious (rcs, vers->version); + } + if (!maybe_duplicate) + break; + } + oldvers = vers; + } + free (cmp); + return result; + } + + + + /* translate the soft tag to branch+date or tag */ + static char * + RCS_locate_softtag_and_date (RCSNode *rcs, const char *tag, const char *date) + { + char *result = NULL; + Soft_Tag *st = tag_is_soft(rcs, tag, 0); + + /* Note: we could have checked if tag is valid. however, since + * tag_check_valid() does a check that might be on the whole repository, + * this seems dangerous if we have thousands of tags in stags (which I + * expect to have soon...), so checking it on soft_tags_read() will take a + * very long time. + * current behavior if using non-existent tag/branch names in stags is that + * no revision is brought, i.e. version with with that tag does not exist + * (which happens to be true). + */ + + /* if looking up a branch and a date was given that is before the date + * specified for that branch, return NULL */ + if (st && st->is_branch && date && st->date && (strcmp(date, st->date) < 0)) + return NULL; + + result = RCS_getversion (rcs, tag, NULL, 1, (int *) NULL); + if (date) + { + char *branch = RCS_whatbranch (rcs, tag); + if (!branch) + return result; + result = strcmp(branch, "1") ? + RCS_getdatebranch (rcs, date, branch) : + RCS_getdatetrunk (rcs, date, 1); + } + return result; + } + + + + /* Try to translate tag as a soft tag + * if lookup is true, the tag must exist in stags + * If force is false and tag name is in the RCS file, return NULL + * (to fallback to the normal tag translation mechanism) + */ + char * + RCS_getsofttag (RCSNode *rcs, const char *tag, bool lookup, bool force) + { + Soft_Tag *st = tag_is_soft (rcs, tag, 1); + if (!st) + { + if (lookup) + error (1, 0, "cannot find soft tag %s", tag); + return NULL; + } + + /* translate the soft tag to branch+date or tag */ + return RCS_locate_softtag_and_date (rcs, st->onsymbol, st->date); + } + + + + /* Translate special/symbolic tags into their revision thus: + * + * - If TAG starts numeric, rely on its formating up to the first + * non-numberic-tag character ([^0-9.]) to resolve a base revision. + * - Else, resolve everything before the first `.' as a symbolic tag to + * determine the base tag. Convert magic branch numbers into their + * physical equivalent. + * - Resolve any remaining tag extensions (.trunk, .head, ...). + * + * RETURNS + * NULL on error. + * A newly malloc'd string containing the resolved revision, otherwise. + * + * ASSUMPTIONS + * The Tag is valid, it has been validated by RCS_check_tag + */ + static char * + translate_tag (RCSNode *rcs, const char *tag, bool keepmagic) + { + /* printf("translate_tag: %s\n",tag); */ + char c; + char *retval = NULL; + char *tmp, *tmpval; + bool dotstart = false; + + assert (rcs && tag); + + if (rcs->flags & PARTIAL) + RCS_reparsercsfile (rcs, NULL, NULL); + + if (tag[0] == '@') + { + /* handle cvsnt compatibility stuff */ + if (tag[1] == '<') + return RCS_getcommitid (rcs, tag + 2, true); + else + return RCS_getcommitid (rcs, tag + 1, false); + } + + tmpval = xstrdup (tag); + if (isdigit ((unsigned char) *tmpval)) + { + /* extract initial revision num */ + char *p = tmpval; + do + ++p; + while (isdigit ((unsigned char) *p) || *p == '.'); + tmp = p; + if (*p--) *p = '\0'; + retval = xstrdup (tmpval); + } + else + tmp = tmpval; + + char *token = strtok (tmp,"."); + if (token) + { + bool force; + if (!keepmagic && retval && RCS_nodeisbranch (rcs, retval)) + { + assert (*token); /* see => assumptions */ + /* We have an initial numeric revision, check + * for magic rev numbers and convert to their + * physical equivalent if so. + */ + char *p = RCS_whatbranch (rcs, retval); + free (retval); + retval = p; + } + do + { + assert (*token); /* see => assumptions */ + force = false; + if (!retval) + { + /* there is no base revision and no initial numeric revision */ + if (token == tmp) + { + char *soft_tag_rev; + + /* check if this is a soft tag */ + if ((soft_tag_rev = RCS_getsofttag (rcs, tag, 0, 0))) + return xstrdup (soft_tag_rev); + + /* tag does not start with a dot */ + retval = translate_symtag (rcs, token); + if (retval) + { + if (keepmagic && (token = strtok (NULL,"."))) + { + /* The next token needs to be evaluated here because + * we need to know whether magic revision numbers + * need to be converted to their physical equivalent. + * Set force flag to not lose this token + */ + force = true; + keepmagic = false; + } + + if (!keepmagic && retval && RCS_nodeisbranch (rcs, retval)) + { + /* convert magic rev numbers into their + * physical equivalent + */ + char *p = RCS_whatbranch (rcs, retval); + free (retval); + retval = p; + if (!retval) force = false; + } + } + } + else if (STREQ (token, TAG_TRUNK)) + { + /* .trunk is a branch tag, but rcs->head is a revision. */ + char *p; + retval = RCS_head (rcs); + + if (retval) + { + /* A non-null return from RCS_head is guaranteed to not + * specify a branch and to have at least one dot. + */ + p = strrchr (retval, '.'); + *p = '\0'; + } + } + else if (STREQ (token, TAG_COMMITID)) + { + char *commitid = strtok (NULL,"."); + if (token = strtok (NULL,".")) + /* The next token needs to be evaluated here because + * RCS_getcommitid needs to know whether a previous + * revision is requested (performance enhancement). + * Set force flag to ensure the next token gets resolved + * if it is not a '.prev' token. + */ + force = true; + if (commitid) + { + bool previous = (token && STREQ (token, TAG_PREVIOUS)); + retval = RCS_getcommitid (rcs, commitid, previous); + if (previous || !retval) + force = false; + } + } + else if (!STREQ (token, TAG_DOTBASE)) + /* Does it make sense to output an error msg here? + * Actualy this is more or less a help for debugging + * since this only happens if the assumptions fail + */ + error (1, 0, "Tag `%s': invalid head: `%s'", token, tag); + + /* If no retval and no force flag => return NULL. + * Callers will generate the "TAG not found" message. + */ + } + else + { + char *p = retval; + if (STREQ (token, TAG_DOTHEAD)) + retval = RCS_branch_head (rcs, p); + else if (STREQ (token, TAG_PREVIOUS)) + retval = RCS_getprevious (rcs, p); + else if (STREQ (token, TAG_ORIGIN)) + retval = RCS_getorigin (rcs, p); + else if (STREQ (token, TAG_ROOT)) + retval = RCS_getroot (rcs, p); + else if (STREQ (token, TAG_NEXT)) + retval = RCS_getnext (rcs, p); + else if (STREQ (token, TAG_SOFT)) + retval = RCS_getsofttag (rcs, p, 1, 1); + else + /* Does it make sense to output an error msg here? + * Actualy this is more or less a help for debugging + * since this only happens if the assumptions fail + */ + error (1, 0, + "Tag `%s': invalid extension: `%s'", token, tag); + free (p); + } + } + while (force || (retval && (token = strtok (NULL, "."))) ); + } + free (tmpval); + /* printf("translate_tag: '%s' => '%s'\n",tag,retval); */ + return retval; + } + + + + /* * Return the version associated with a particular symbolic tag. * Returns NULL or a newly malloc'd string. */ static char * translate_symtag (RCSNode *rcs, const char *tag) { ! /* char *soft_tag_rev; */ if (rcs->symbols != NULL) { *************** *** 3374,3379 **** --- 4305,4472 ---- /* + * Do some consistency checks ... + * If a symbolic tag is found, return a newly allocated string + * Allow only: + * SYMTAG | SYMTAG[.prev]* | .trunk[.prev]* | HEAD | BASE | x.x.x[.prev]* + * + * ERRORS + * fatal errors are generated for illegal syntax + */ + char * + RCS_extract_tag (const char *tag, bool files) + { + char *retval = NULL; + const char *p = tag; + bool first = true; + + assert(p); + + if (*p == '@') + { + if (*(p+1) == '<') + { + retval = xstrdup (p+1); + *retval = '@'; + } + else + retval = xstrdup (p); + return retval; + } + + if (strstr (p,"..")) + error (1, 0, "\ + Numeric tag `%s' invalid. Numeric tags should be of the form X[.X]...", tag); + + bool dot = false; + while (p) + { + if (*p == '.') + dot = true; + else if (!isdigit ((unsigned char) *p)) + break; + else if (dot && first) + error (1, 0, "\ + Numeric tag `%s' invalid. Numeric tags should be of the form X[.X]...", tag); + else + { + dot = false; + first = false; + } + ++p; + } + + if ( (*p && !first && !dot) || tag[strlen (tag)-1] == '.') + error (1, 0, "\ + Tag `%s' invalid. Combined tags should be of the form X[.X]...", tag); + + bool deptag = false; + bool multi = true; + char *prev = NULL; + char *tmp = xstrdup (p); + char *token = strtok(tmp,"."); + if (token) + { + do + { + if (first) + { + if (!dot) + { + if (STREQ (token, TAG_HEAD) + || STREQ (token, TAG_BASE)) + { + deptag = true; + first = false; + } + else if (!STREQ (token, TAG_TRUNK) + && !STREQ (token, TAG_COMMITID) + && !STREQ (token, TAG_PREVIOUS) + && !STREQ (token, TAG_NEXT) + && !STREQ (token, TAG_DOTHEAD) + && !STREQ (token, TAG_DOTBASE) + && !STREQ (token, TAG_ORIGIN) + && !STREQ (token, TAG_ROOT)) + { + RCS_check_tag (token); + retval = xstrdup (token); + first = false; + } + else + error (1, 0,"\ + Tag `%s' invalid. Reserved expression without leading dot: `%s'", tag, token); + } + else if (STREQ (token, TAG_TRUNK)) + { + first = false; + } + else if (STREQ (token, TAG_DOTBASE)) + { + first = false; + multi = false; + } + else if (STREQ (token, TAG_COMMITID)) + { + token = strtok (NULL,"."); + if (token) + { + retval = Xasprintf ("@%s",token); + first = false; + } + } + else if (!files) + error (1, 0,"\ + Tag `%s' invalid. Tag must not be relative: `.%s'", tag, token); + else if (STREQ (token, TAG_ORIGIN) + || STREQ (token, TAG_DOTHEAD)) + { + first = false; + prev = token; + } + else if (STREQ (token, TAG_PREVIOUS) + || STREQ (token, TAG_NEXT) + || STREQ (token, TAG_ROOT)) + { + first = false; + } + else + error (1, 0,"\ + Tag `%s' invalid. Cannot resolve head: `.%s'", tag, token); + } + else if (deptag) + error (1, 0,"\ + Tag `%s' invalid. Deprecated prefix before extension: `%s'", tag, token); + else if (!multi) + error (1, 0,"\ + Tag `%s' invalid. Extension not allowed: `%s'", tag, token); + else if (STREQ (token, TAG_ORIGIN) + || STREQ (token, TAG_DOTHEAD)) + { + if (!prev || !STREQ (prev, token)) + prev = token; + else + error (1, 0,"\ + Tag `%s' invalid. Duplicate extension: `%s'", tag, token); + + } + else if ((!STREQ (token, TAG_PREVIOUS)) + && (!STREQ (token, TAG_NEXT)) + && (!STREQ (token, TAG_ROOT))) + error (1, 0,"\ + Tag `%s' invalid. Cannot resolve extension: `%s'", tag, token); + else + prev = NULL; + } + while (!first && (token = strtok (NULL, ".")) ); + } + free (tmp); + + return retval; + } + + + + /* * TRUE if argument has valid syntax for an RCS revision or * branch number. All characters must be digits or dots, first * and last characters must be digits, and no two consecutive *************** *** 3520,3525 **** --- 4613,4622 ---- void free_keywords (void *keywords) { + struct rcs_keyword *k; + k = (struct rcs_keyword *) keywords + KEYWORD_LOCALID; + if (k->string) + free ((char *) k->string); free (keywords); } *************** *** 3905,3910 **** --- 5002,5008 ---- { error (0, 0, "Skipping `$" "Log$' keyword due to excessive comment leader."); + free (sub); continue; } } *************** *** 4790,4815 **** len = dot - r; new_r = xmalloc (len + 1); memcpy (new_r, r, len); ! *(new_r + len) = '\0'; return new_r; } - /* Revision number string, R, must contain a `.'. - R must be writable. Replace the rightmost `.' in R with - the NUL byte and return a pointer to that NUL byte. */ - static char * - truncate_revnum_in_place (char *r) - { - char *dot = strrchr (r, '.'); - assert (dot); - *dot = '\0'; - return dot; - } - - - /* Revision number strings, R and S, must each contain a `.'. R and S must be writable and must have the same number of dots. Truncate R and S for the comparison, then restored them to their --- 5888,5899 ---- len = dot - r; new_r = xmalloc (len + 1); memcpy (new_r, r, len); ! new_r[len] = '\0'; return new_r; } /* Revision number strings, R and S, must each contain a `.'. R and S must be writable and must have the same number of dots. Truncate R and S for the comparison, then restored them to their *************** *** 5827,5833 **** /* FIXME: This check should be moved to RCS_check_tag. There is no reason for it to be here. */ if (STREQ (tag, TAG_BASE) ! || STREQ (tag, TAG_HEAD)) { /* Print the name of the tag might be considered redundant with the caller, which also prints it. Perhaps this helps --- 6911,6918 ---- /* FIXME: This check should be moved to RCS_check_tag. There is no reason for it to be here. */ if (STREQ (tag, TAG_BASE) ! || STREQ (tag, TAG_HEAD) ! || *tag == '.') { /* Print the name of the tag might be considered redundant with the caller, which also prints it. Perhaps this helps Index: home/ortal/ccvs/src/rcs.h diff -c home/ortal/ccvs/src/rcs.h:1.2.2.3 home/ortal/ccvs/src/rcs.h:1.9 *** home/ortal/ccvs/src/rcs.h:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/rcs.h Sun Jun 24 19:48:37 2007 *************** *** 209,228 **** char *RCS_tag2rev (RCSNode *rcs, char *tag); char *RCS_getversion (RCSNode *rcs, const char *tag, const char *date, int force_tag_match, int *simple_tag); char *RCS_magicrev (RCSNode *rcs, char *rev); int RCS_isbranch (RCSNode *rcs, const char *rev); ! int RCS_nodeisbranch (RCSNode *rcs, const char *tag); char *RCS_whatbranch (RCSNode *rcs, const char *tag); char *RCS_head (RCSNode * rcs); int RCS_datecmp (const char *date1, const char *date2); time_t RCS_getrevtime (RCSNode * rcs, const char *rev, char *date, int fudge); List *RCS_symbols (RCSNode *rcs); void RCS_check_tag (const char *tag); int RCS_valid_rev (const char *rev); List *RCS_getlocks (RCSNode *rcs); void freercsnode (RCSNode ** rnodep); char *RCS_getbranch (RCSNode *rcs, const char *tag, int force_tag_match); ! char *RCS_branch_head (RCSNode *rcs, char *rev); int RCS_isdead (RCSNode *, const char *); char *RCS_getexpand (RCSNode *); --- 209,230 ---- char *RCS_tag2rev (RCSNode *rcs, char *tag); char *RCS_getversion (RCSNode *rcs, const char *tag, const char *date, int force_tag_match, int *simple_tag); + char *RCS_getsofttag (RCSNode *rcs, const char *tag, bool lookup, bool force); char *RCS_magicrev (RCSNode *rcs, char *rev); int RCS_isbranch (RCSNode *rcs, const char *rev); ! bool RCS_nodeisbranch (RCSNode *rcs, const char *tag); char *RCS_whatbranch (RCSNode *rcs, const char *tag); char *RCS_head (RCSNode * rcs); int RCS_datecmp (const char *date1, const char *date2); time_t RCS_getrevtime (RCSNode * rcs, const char *rev, char *date, int fudge); List *RCS_symbols (RCSNode *rcs); void RCS_check_tag (const char *tag); + char *RCS_extract_tag (const char *tag, bool files); int RCS_valid_rev (const char *rev); List *RCS_getlocks (RCSNode *rcs); void freercsnode (RCSNode ** rnodep); char *RCS_getbranch (RCSNode *rcs, const char *tag, int force_tag_match); ! char *RCS_branch_head (RCSNode *rcs, const char *tag); int RCS_isdead (RCSNode *, const char *); char *RCS_getexpand (RCSNode *); *************** *** 253,258 **** --- 255,262 ---- void RCS_setincexc (void **, const char *arg); void RCS_setlocalid (const char *, unsigned int, void **, const char *arg); char *make_file_label (const char *, const char *, RCSNode *); + bool RCS_is_symbolic (const char *); + bool RCS_is_relative (const char *); extern bool preserve_perms; Index: home/ortal/ccvs/src/rcscmds.c diff -c home/ortal/ccvs/src/rcscmds.c:1.2.2.3 home/ortal/ccvs/src/rcscmds.c:1.9 *** home/ortal/ccvs/src/rcscmds.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/rcscmds.c Thu Jun 7 09:46:38 2007 *************** *** 239,245 **** cvs_output ("\n", 1); tmp1 = cvs_temp_name(); ! if (RCS_checkout (rcs, NULL, xrev1, rev1, options, tmp1, NULL, NULL)) { cvs_outerr ("rcsmerge: co failed\n", 0); exit (EXIT_FAILURE); --- 239,247 ---- cvs_output ("\n", 1); tmp1 = cvs_temp_name(); ! if (!RCS_isdead(rcs, xrev1) && ! RCS_checkout (rcs, NULL, xrev1, rev1, options, tmp1, ! NULL, NULL)) { cvs_outerr ("rcsmerge: co failed\n", 0); exit (EXIT_FAILURE); *************** *** 284,295 **** call_diff_add_arg (tmp1); call_diff_add_arg (tmp2); ! retval = call_diff3 (diffout); ! if (retval == 1) ! cvs_outerr ("rcsmerge: warning: conflicts during merge\n", 0); ! else if (retval == 2) ! exit (EXIT_FAILURE); if (diffout) copy_file (diffout, workfile); --- 286,322 ---- call_diff_add_arg (tmp1); call_diff_add_arg (tmp2); ! if (merge_binary_identical && ! (options && !strcmp(options, "-kb")) || wrap_merge_is_copy(workfile)) ! { ! if (!xcmp(tmp1, workfile)) ! { ! copy_file (tmp2, diffout); ! retval = 0; ! } ! else if (!xcmp(tmp2, workfile)) ! { ! /* workfile already includes merge changes */ ! copy_file (workfile, diffout); ! retval = 0; ! } ! else ! { ! copy_file (tmp2, diffout); ! retval = 1; /* conflict */ ! cvs_outerr ("rcsmerge: warning: nonmergeable file needs merge\n", ! 0); ! } ! } ! else ! { ! retval = call_diff3 (diffout); ! if (retval == 1) ! cvs_outerr ("rcsmerge: warning: conflicts during merge\n", 0); ! else if (retval == 2) ! exit (EXIT_FAILURE); ! } if (diffout) copy_file (diffout, workfile); Index: home/ortal/ccvs/src/repos.c diff -c home/ortal/ccvs/src/repos.c:1.3.2.3 home/ortal/ccvs/src/repos.c:1.9 *** home/ortal/ccvs/src/repos.c:1.3.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/repos.c Thu Jun 7 09:46:38 2007 *************** *** 14,20 **** --- 14,54 ---- #include "cvs.h" #include "getline.h" + #ifdef STICKY_MODULES + char * + read_module_name (char *dir, char *update_dir) + { + FILE *fpin; + char *mname = NULL; + size_t mname_allocated = 0; + char *tmp; + char *cp; + if (dir != NULL) + tmp = Xasprintf("%s/%s", dir, CVSADM_MODULE_NAME); + else + tmp = xstrdup (CVSADM_MODULE_NAME); + + fpin = CVS_FOPEN (tmp, "r"); + + if (fpin == NULL) + return NULL; + + if (getline (&mname, &mname_allocated, fpin) < 0) + { + /* FIXME: should be checking for end of file separately. */ + error (1, errno, "cannot read %s", tmp); + } + if (fclose (fpin) < 0) + error (0, errno, "cannot close %s", tmp); + free (tmp); + + if ((cp = strrchr (mname, '\n')) != NULL) + *cp = '\0'; /* strip the newline */ + + return mname; + } + #endif /* Determine the name of the RCS repository for directory DIR in the current working directory, or for the current working directory Index: home/ortal/ccvs/src/root.c diff -c home/ortal/ccvs/src/root.c:1.2.2.3 home/ortal/ccvs/src/root.c:1.9 *** home/ortal/ccvs/src/root.c:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/root.c Thu Jun 7 09:46:38 2007 *************** *** 17,22 **** --- 17,23 ---- #include "cvs.h" #include #include "getline.h" + #include "savecwd.h" /* Printable names for things in the current_parsed_root->method enum variable. Watch out if the enum is changed in cvs.h! */ *************** *** 269,275 **** static void delconfig (Node *n) { ! if (n->data) free_config (n->data); } --- 270,280 ---- static void delconfig (Node *n) { ! if (n->data) ! { ! free_config (n->data); ! n->data = NULL; ! } } *************** *** 381,386 **** --- 386,392 ---- newroot->original = NULL; newroot->directory = NULL; + newroot->dirpath = NULL; newroot->method = null_method; newroot->isremote = false; #ifdef CLIENT_SUPPORT *************** *** 393,398 **** --- 399,405 ---- newroot->proxy_hostname = NULL; newroot->proxy_port = 0; newroot->redirect = true; /* Advertise Redirect support */ + newroot->isremote = 0; #endif /* CLIENT_SUPPORT */ return newroot; *************** *** 414,419 **** --- 421,428 ---- free (root->original); if (root->directory != NULL) free (root->directory); + if (root->dirpath != NULL) + free (root->dirpath); #ifdef CLIENT_SUPPORT if (root->username != NULL) free (root->username); *************** *** 438,443 **** --- 447,484 ---- /* + * Return the canonicalized absolute pathname, if one exists. + * A NULL is returned if the path is NULL or "" or if the + * path does not exist as a directory (yet). + */ + static char * + expand_directory (path) + const char *path; + { + struct saved_cwd cwd; + char *normalized_path = NULL; + + if (path == NULL || *path == '\0') + return NULL; + + if ( isdir (path) ) + { + /* Try to normalize using xgetcwd(). */ + if (save_cwd (&cwd)) + error (1, 0, "can't save cwd"); + if (chdir (path) < 0) + error (1, errno, "can't change to %s", path); + normalized_path = xgetcwd(); + if (restore_cwd (&cwd, 0)) + error (1, errno, "can't restore cwd"); + free_cwd (&cwd); + } + + return normalized_path; + } + + + /* * Parse a CVSROOT string to allocate and return a new cvsroot_t structure. * Valid specifications are: * *************** *** 882,888 **** error (0, 0, "Missing directory in CVSROOT."); goto error_exit; } ! /* Hooray! We finally parsed it! */ free (cvsroot_save); --- 923,932 ---- error (0, 0, "Missing directory in CVSROOT."); goto error_exit; } ! ! if (newroot->method == local_method) ! newroot->dirpath = expand_directory (newroot->directory); ! /* Hooray! We finally parsed it! */ free (cvsroot_save); *************** *** 993,998 **** --- 1037,1043 ---- * and, otherwise, we want no trailing slashes. */ Sanitize_Repository_Name (newroot->directory); + newroot->dirpath = expand_directory (newroot->directory); #ifdef PROXY_SUPPORT /* Translate the directory to a local one in the case that we are Index: home/ortal/ccvs/src/root.h diff -c home/ortal/ccvs/src/root.h:1.2.2.3 home/ortal/ccvs/src/root.h:1.7 *** home/ortal/ccvs/src/root.h:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/root.h Thu Jun 7 09:46:38 2007 *************** *** 31,36 **** --- 31,37 ---- char *original; /* The complete source CVSroot string. */ CVSmethod method; /* One of the enum values above. */ char *directory; /* The directory name. */ + char *dirpath; /* the normalized CVSROOT path. */ bool isremote; /* True if we are doing remote access. */ /* The following is required for servers now to allow Redirects to be sent * for remote roots when client support is disabled. Index: home/ortal/ccvs/src/run.c diff -c home/ortal/ccvs/src/run.c:1.2.2.2 home/ortal/ccvs/src/run.c:1.3 *** home/ortal/ccvs/src/run.c:1.2.2.2 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/run.c Thu Jun 7 09:46:41 2007 *************** *** 84,90 **** case '"': case '\'': if (inquotes == *d) inquotes = '\0'; ! else inquotes = *d; break; case ' ': case '\t': --- 84,91 ---- case '"': case '\'': if (inquotes == *d) inquotes = '\0'; ! else if (!inquotes) inquotes = *d; ! else d++; break; case ' ': case '\t': Index: home/ortal/ccvs/src/sanity-multifiles.sh diff -c /dev/null home/ortal/ccvs/src/sanity-multifiles.sh:1.3 *** /dev/null Mon Jul 30 12:14:09 2007 --- home/ortal/ccvs/src/sanity-multifiles.sh Tue Dec 9 20:34:15 2003 *************** *** 0 **** --- 1,74 ---- + #!/bin/bash + + run_cvs() + { + $CVSPATH "$@" + [ "$?" != 0 ] && { + echo "failed cvs $@" + exit 1 + } + } + + # the test directory (like /tmp/cvs-sanity) + tdir=/home/amirva/cvs-test + # clean up the test directory and create a new one + rm -rf $tdir $tdir.* + mkdir $tdir.real + ln -snf $tdir.real $tdir + + # the CVS we want to test + CVSPATH=/home/amirva/cvs.merge/src/cvs + CVS=run_cvs + export CVSROOT=:pserver:amirva@localhost:2405$tdir/cvsroot + export cvsroot=$tdir/cvsroot + + # build the respository + cd $tdir + $CVS -d $cvsroot init + mkdir $cvsroot/rep + + # check if we are logged in, if not - ask user for login password + $CVSPATH co -c || { + $CVS login + } + + $CVS co rep + cd rep + # add 100 files + ndirs=10 + nfiles=10 + f= d= + for ((i=0; i $j + f="$f $i/$j" + done + cd .. + done + $CVS add $d + $CVS add $f + $CVS ci -m "add files" + + # modify 100 files + for ff in $f ; do + echo "modify on MAIN" >> $ff + done + $CVS ci -m "commit modify" + + # create a branch + $CVS tag -b br1 + $CVS up -r br1 + + # modify 100 files + for ff in $f ; do + echo "brmod" >> $ff + done + $CVS ci -m "modify on br1" + + $CVS up -A + $CVS up -j br1 + $CVS ci -m "br1 merge to MAIN" + Index: home/ortal/ccvs/src/sanity.sh diff -c home/ortal/ccvs/src/sanity.sh:1.2.2.3 home/ortal/ccvs/src/sanity.sh:1.35 *** home/ortal/ccvs/src/sanity.sh:1.2.2.3 Sun Oct 9 16:27:24 2005 --- home/ortal/ccvs/src/sanity.sh Sun Jul 8 17:21:39 2007 *************** *** 1,5 **** #! /bin/sh - : # sanity.sh -- a growing testsuite for cvs. # # The copyright notice said: "Copyright (C) 1992, 1993 Cygnus Support" --- 1,4 ---- *************** *** 372,378 **** exit 1 fi if $CVS_RSH $remotehost "${servercvs} --version /dev/null 2>&1"; then :; else echo "CVS executable \`$remotehost:${servercvs}' does not contain server support." >&2 exit 1 fi --- 371,377 ---- exit 1 fi if $CVS_RSH $remotehost "${servercvs} --version /dev/null 2>&1"; then :; else echo "CVS executable \`$remotehost:${servercvs}' does not contain server support." >&2 exit 1 fi *************** *** 387,394 **** exit 1 fi if ${servercvs} --version /dev/null 2>&1; then :; else ! echo "CVS executable \`${servercvs}' does not contain server support." >&2 exit 1 fi fi --- 386,393 ---- exit 1 fi if ${servercvs} --version /dev/null 2>&1; then :; else ! echo "CVS executable \`${servercvs}' does not contain server support:xxx$xx." >&2 exit 1 fi fi *************** *** 398,404 **** # support. if $remote; then if ${testcvs} --version /dev/null 2>&1; then :; else echo "CVS executable \`${testcvs}' does not contain client support." >&2 exit 1 fi --- 397,403 ---- # support. if $remote; then if ${testcvs} --version /dev/null 2>&1; then :; else echo "CVS executable \`${testcvs}' does not contain client support." >&2 exit 1 fi *************** *** 450,456 **** --- 449,465 ---- # MT (tagged text - see doc/cvs-client.texi) to request that the client print # its own name. SPROG=`basename ${servercvs} |sed 's/\.exe$//'` + if [ "${SPROG%%*valgrind*}" == "" ] ; then + SPROG='[a-z-]*cvs' + fi + use_valgrind=0 + echo $testcvs | grep valgrind-cvs 2>&1 1>/dev/null + if ((!$?)) ; then + SPROG="[a-z\-]*cvs" + CPROG="[a-z\-]*cvs" + use_valgrind=1 + fi # Match the hostname hostname="[-_.a-zA-Z0-9]*" *************** *** 1375,1380 **** --- 1384,1397 ---- cat ${TESTDIR}/dotest.tmp >>${LOGFILE} fail "$1" fi + if ((use_valgrind)); then + d=`echo $testcvs | sed -e "s/valgrind-cvs/valgrind.log/"` + f=`ls -1tr $d | tail -1` + echo $f | grep "\-" 2>&1 1>/dev/null + if (($?)) ; then + mv $d/$f "$d/$f-$1" + fi + fi } dotest_all_in_one () *************** *** 1637,1642 **** --- 1654,1661 ---- tests="${tests} new newb conflicts conflicts2 conflicts3" tests="${tests} clean" tests="${tests} keywordexpand" + tests="${tests} tag-ext" + tests="${tests} soft-tags" # Checking out various places (modules, checkout -d, &c) tests="${tests} modules modules2 modules3 modules4 modules5 modules6" tests="${tests} modules7 mkmodules co-d" *************** *** 1658,1665 **** tests="${tests} serverpatch log log2 logopt ann ann-id" # Repository Storage (RCS file format, CVS lock files, creating # a repository without "cvs init", &c). ! tests="${tests} crerepos rcs rcs2 rcs3 rcs4 rcs5" ! tests="$tests lockfiles backuprecover" tests="${tests} sshstdio" # More history browsing, &c. tests="${tests} history" --- 1677,1684 ---- tests="${tests} serverpatch log log2 logopt ann ann-id" # Repository Storage (RCS file format, CVS lock files, creating # a repository without "cvs init", &c). ! tests="${tests} crerepos rcs rcs2 rcs3 rcs4 rcs5 lockdir" ! tests="${tests} lockfiles backuprecover" tests="${tests} sshstdio" # More history browsing, &c. tests="${tests} history" *************** *** 1682,1687 **** --- 1701,1708 ---- tests="${tests} dottedroot fork commit-d template" tests="${tests} writeproxy writeproxy-noredirect writeproxy-ssh" tests="${tests} writeproxy-ssh-noredirect" + # Jungo additions + tests="${tests} binarymerge createdeadrev precommitlog" else tests="$*" fi *************** *** 2822,2829 **** #Secondary Server: Concurrent Versions System (CVS) [0-9p.]* (.*server)' if $remote; then dotest version-2r "${testcvs} version" \ ! 'Client: Concurrent Versions System (CVS) [0-9p.]* (client.*) ! Server: Concurrent Versions System (CVS) [0-9p.]* (.*server)' else dotest version-2 "${testcvs} version" \ 'Concurrent Versions System (CVS) [0-9.]*.*' --- 2843,2850 ---- #Secondary Server: Concurrent Versions System (CVS) [0-9p.]* (.*server)' if $remote; then dotest version-2r "${testcvs} version" \ ! 'Client: Concurrent Versions System (CVS) [0-9p.]*.* (client/server)\( ([a-zA-Z ]*)\)\? ! Server: Concurrent Versions System (CVS) [0-9p.]*.* (client/server)\( ([a-zA-Z ]*)\)\?' else dotest version-2 "${testcvs} version" \ 'Concurrent Versions System (CVS) [0-9.]*.*' *************** *** 2884,2893 **** # that I consider to be more correct, but local cvs prints the # "nothing known" message and noone has gotten around to fixing it. dotest_fail basica-notadded "${testcvs} -q ci ssfile" \ ! "${CPROG} commit: use .${CPROG} add. to create an entry for \`ssfile' ! ${CPROG}"' \[commit aborted\]: correct above errors first!' \ ! "${CPROG}"' commit: nothing known about `ssfile'\'' ! '"${CPROG}"' \[commit aborted\]: correct above errors first!' dotest basica-4 "${testcvs} add ssfile" \ "${SPROG}"' add: scheduling file `ssfile'\'' for addition --- 2905,2914 ---- # that I consider to be more correct, but local cvs prints the # "nothing known" message and noone has gotten around to fixing it. dotest_fail basica-notadded "${testcvs} -q ci ssfile" \ ! "${SPROG} commit: use .${SPROG} add. to create an entry for \`ssfile' ! ${SPROG}"' \[commit aborted\]: correct above errors first!' \ ! "${SPROG}"' commit: nothing known about `ssfile'\'' ! '"${SPROG}"' \[commit aborted\]: correct above errors first!' dotest basica-4 "${testcvs} add ssfile" \ "${SPROG}"' add: scheduling file `ssfile'\'' for addition *************** *** 4705,4710 **** --- 4726,4732 ---- postwatch preproxy rcsinfo + stags taginfo verifymsg" dotest ls-2 "$testcvs ls -R" \ *************** *** 4725,4730 **** --- 4747,4753 ---- postwatch preproxy rcsinfo + stags taginfo verifymsg" # This used to cause a fatal error. *************** *** 4748,4753 **** --- 4771,4777 ---- postwatch preproxy rcsinfo + stags taginfo verifymsg" *************** *** 4774,4779 **** --- 4798,4804 ---- postwatch preproxy rcsinfo + stags taginfo verifymsg *************** *** 7522,7527 **** --- 7547,7553 ---- postwatch preproxy rcsinfo + stags taginfo verifymsg Emptydir *************** *** 7553,7558 **** --- 7579,7585 ---- ---- $ISO8601DATE 1\.[0-9][0-9]* postwatch ---- $ISO8601DATE 1\.[0-9][0-9]* preproxy ---- $ISO8601DATE 1\.[0-9][0-9]* rcsinfo + ---- $ISO8601DATE 1\.[0-9][0-9]* stags ---- $ISO8601DATE 1\.[0-9][0-9]* taginfo ---- $ISO8601DATE 1\.[0-9][0-9]* verifymsg d--- $ISO8601DATE Emptydir *************** *** 7584,7589 **** --- 7611,7617 ---- /postwatch/1\.[0-9][0-9]*/$DATE// /preproxy/1\.[0-9][0-9]*/$DATE// /rcsinfo/1\.[0-9][0-9]*/$DATE// + /stags/1\.[0-9][0-9]*/$DATE// /taginfo/1\.[0-9][0-9]*/$DATE// /verifymsg/1\.[0-9][0-9]*/$DATE// D/Emptydir//// *************** *** 7614,7619 **** --- 7642,7648 ---- postwatch preproxy rcsinfo + stags taginfo verifymsg Emptydir *************** *** 11990,12321 **** "${SPROG} update: \`file1' is no longer in the repository ${SPROG} update: \`file2' is no longer in the repository" ! # OK, now add a directory to both working directories ! # and see that CVS doesn't lose its mind. ! mkdir sdir ! dotest conflicts3-14 "${testcvs} add sdir" \ ! "Directory ${CVSROOT_DIRNAME}/first-dir/sdir added to the repository" ! touch sdir/sfile ! dotest conflicts3-14a "${testcvs} add sdir/sfile" \ ! "${SPROG} add: scheduling file .sdir/sfile. for addition ! ${SPROG} add: use .${SPROG} commit. to add this file permanently" ! dotest conflicts3-14b "${testcvs} -q ci -m add" \ ! "$CVSROOT_DIRNAME/first-dir/sdir/sfile,v <-- sdir/sfile ! initial revision: 1\.1" ! cd ../../2/first-dir ! # Create a CVS directory without the proper administrative ! # files in it. This can happen for example if you hit ^C ! # in the middle of a checkout. ! mkdir sdir ! mkdir sdir/CVS ! # OK, in the local case CVS sees that the directory exists ! # in the repository and recurses into it. In the remote case ! # CVS can't see the repository and has no way of knowing ! # that sdir is even a directory (stat'ing everything would be ! # too slow). The remote behavior makes more sense to me (but ! # would this affect other cases?). ! if $remote; then ! dotest conflicts3-15 "${testcvs} -q update" \ ! "${QUESTION} sdir" ! else ! dotest conflicts3-15 "${testcvs} -q update" \ ! "${QUESTION} sdir ! ${SPROG} update: ignoring sdir (CVS/Repository missing)" ! touch sdir/CVS/Repository ! dotest conflicts3-16 "${testcvs} -q update" \ ! "${QUESTION} sdir ! ${SPROG} update: ignoring sdir (CVS/Entries missing)" ! cd .. ! dotest conflicts3-16a "${testcvs} -q update first-dir" \ ! "${QUESTION} first-dir/sdir ! ${SPROG} update: ignoring first-dir/sdir (CVS/Entries missing)" ! cd first-dir ! fi ! rm -r sdir ! # OK, now the same thing, but the directory doesn't exist ! # in the repository. ! mkdir newdir ! mkdir newdir/CVS ! dotest conflicts3-17 "${testcvs} -q update" "${QUESTION} newdir" ! echo "D/newdir////" >> CVS/Entries ! dotest conflicts3-18 "${testcvs} -q update" \ ! "${CPROG} update: ignoring newdir (CVS/Repository missing)" ! touch newdir/CVS/Repository ! dotest conflicts3-19 "${testcvs} -q update" \ ! "${CPROG} update: ignoring newdir (CVS/Entries missing)" ! cd .. ! dotest conflicts3-20 "${testcvs} -q update first-dir" \ ! "${CPROG} update: ignoring first-dir/newdir (CVS/Entries missing)" ! cd first-dir ! rm -r newdir ! # The previous tests have left CVS/Entries in something of a mess. ! # While we "should" be able to deal with that (maybe), for now ! # we just start over. ! cd .. ! rm -r first-dir ! dotest conflicts3-20a "${testcvs} -q co -l first-dir" '' ! cd first-dir ! dotest conflicts3-21 "${testcvs} -q update -d sdir" "U sdir/sfile" ! rm -r sdir/CVS ! dotest conflicts3-22 "${testcvs} -q update" "${QUESTION} sdir" ! if $remote; then ! dotest_fail conflicts3-23 "${testcvs} -q update -PdA" \ ! "${QUESTION} sdir ! ${CPROG} update: move away \`sdir/sfile'; it is in the way ! C sdir/sfile" ! else ! dotest conflicts3-23 "${testcvs} -q update -PdA" \ ! "${QUESTION} sdir" ! fi ! # Not that it should really affect much, but let's do the case ! # where sfile has been removed. For example, suppose that sdir ! # had been a CVS-controlled directory which was then removed ! # by removing each file (and using update -P or some such). Then ! # suppose that the build process creates an sdir directory which ! # is not supposed to be under CVS. ! rm -r sdir ! dotest conflicts3-24 "${testcvs} -q update -d sdir" "U sdir/sfile" ! rm sdir/sfile ! dotest conflicts3-25 "${testcvs} rm sdir/sfile" \ ! "${SPROG} remove: scheduling .sdir/sfile. for removal ! ${SPROG} remove: use .${SPROG} commit. to remove this file permanently" ! dotest conflicts3-26 "${testcvs} ci -m remove sdir/sfile" \ ! "${CVSROOT_DIRNAME}/first-dir/sdir/sfile,v <-- sdir/sfile ! new revision: delete; previous revision: 1\.1" ! rm -r sdir/CVS ! dotest conflicts3-27 "${testcvs} -q update" "${QUESTION} sdir" ! dotest conflicts3-28 "${testcvs} -q update -PdA" \ ! "${QUESTION} sdir" ! dokeep ! cd ../.. ! rm -r 1 2 ! modify_repo rm -rf $CVSROOT_DIRNAME/first-dir ! ;; ! clean) ! # Test update -C (overwrite local mods w/ repository copies) ! mkdir 1; cd 1 ! dotest clean-1 "${testcvs} -q co -l ." '' ! mkdir first-dir ! dotest clean-2 "${testcvs} add first-dir" \ ! "Directory ${CVSROOT_DIRNAME}/first-dir added to the repository" cd first-dir ! echo "The usual boring test text." > cleanme.txt ! dotest clean-3 "${testcvs} add cleanme.txt" \ ! "${SPROG} add: scheduling file .cleanme\.txt. for addition ! ${SPROG} add: use .${SPROG} commit. to add this file permanently" ! dotest clean-4 "${testcvs} -q ci -m clean-3" \ ! "$CVSROOT_DIRNAME/first-dir/cleanme\.txt,v <-- cleanme\.txt ! initial revision: 1\.1" ! # Okay, preparation is done, now test. ! # Check that updating an unmodified copy works. ! dotest clean-5 "${testcvs} -q update" '' ! # Check that updating -C an unmodified copy works. ! dotest clean-6 "${testcvs} -q update -C" '' ! # Check that updating a modified copy works. ! echo "fish" >> cleanme.txt ! dotest clean-7 "${testcvs} -q update" 'M cleanme\.txt' ! # Check that updating -C a modified copy works. ! dotest clean-8 "${testcvs} -q update -C" \ ! "(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1) ! U cleanme\.txt" ! # And check that the backup copy really was made. ! dotest clean-9 "cat .#cleanme.txt.1.1" \ ! "The usual boring test text\. ! fish" ! ! # Do it all again, this time naming the file explicitly. ! rm .#cleanme.txt.1.1 ! dotest clean-10 "${testcvs} -q update cleanme.txt" '' ! dotest clean-11 "${testcvs} -q update -C cleanme.txt" '' ! echo "bluegill" >> cleanme.txt ! dotest clean-12 "${testcvs} -q update cleanme.txt" 'M cleanme\.txt' ! dotest clean-13 "${testcvs} -q update -C cleanme.txt" \ ! "(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1) ! U cleanme\.txt" ! # And check that the backup copy really was made. ! dotest clean-14 "cat .#cleanme.txt.1.1" \ ! "The usual boring test text\. ! bluegill" ! # Now try with conflicts ! cd .. ! dotest clean-15 "${testcvs} -q co -d second-dir first-dir" \ ! 'U second-dir/cleanme\.txt' ! cd second-dir ! echo "conflict test" >> cleanme.txt ! dotest clean-16 "${testcvs} -q ci -m." \ ! "$CVSROOT_DIRNAME/first-dir/cleanme\.txt,v <-- cleanme\.txt ! new revision: 1\.2; previous revision: 1\.1" ! cd ../first-dir ! echo "fish" >> cleanme.txt ! dotest clean-17 "${testcvs} -nq update" \ ! "RCS file: ${CVSROOT_DIRNAME}/first-dir/cleanme\.txt,v ! retrieving revision 1\.1 ! retrieving revision 1\.2 ! Merging differences between 1\.1 and 1\.2 into cleanme\.txt ! rcsmerge: warning: conflicts during merge ! ${SPROG} update: conflicts found in cleanme\.txt ! C cleanme\.txt" ! dotest clean-18 "${testcvs} -q update -C" \ ! "(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1) ! U cleanme\.txt" ! dotest clean-19 "cat .#cleanme.txt.1.1" \ ! "The usual boring test text\. ! fish" ! ! # Done. Clean up. ! dokeep ! cd ../.. ! rm -rf 1 ! modify_repo rm -rf $CVSROOT_DIRNAME/first-dir ! ;; ! keywordexpand) ! # Tests of the original *BSD tag= and keywordexpand= features ! # are done via the LocalKeyword= and KeywordExpand features. ! # Skip this in noredirect mode because it is too easy for the primary ! # and secondary error messages to get out of sync when the ! # CVSROOT/config files are broken. This is intentional, since it is ! # possible and even likely that an administrator might want to set up ! # different configurations on the two servers and the paths to the ! # config files on the secondary and primary were intentionally left ! # intact even though they might be different. ! if $noredirect; then ! notnoredirect keywordexpand ! continue ! fi ! mkdir keywordexpand; cd keywordexpand ! dotest keywordexpand-1 "${testcvs} -q co CVSROOT" \ ! 'U CVSROOT/checkoutlist ! U CVSROOT/commitinfo ! U CVSROOT/config ! U CVSROOT/cvswrappers ! U CVSROOT/loginfo ! U CVSROOT/modules ! U CVSROOT/notify ! U CVSROOT/postadmin ! U CVSROOT/postproxy ! U CVSROOT/posttag ! U CVSROOT/postwatch ! U CVSROOT/preproxy ! U CVSROOT/rcsinfo ! U CVSROOT/taginfo ! U CVSROOT/verifymsg' ! cd CVSROOT ! echo LocalKeyword=MyBSD=CVSHeader >> config ! # First do not expand any keywords ! echo KeywordExpand=i >> config ! dotest keywordexpand-2 "${testcvs} -Q ci -mkeywordexpand config" ! cd .. ! mkdir testimport; cd testimport ! echo '$''Author$' > file1 ! echo '$''Date$' >> file1 ! echo '$''CVSHeader$' >> file1 ! echo '$''Header$' >> file1 ! echo '$''Id$' >> file1 ! echo '$''Locker$' >> file1 ! echo '$''Log$' >> file1 ! echo '$''Name$' >> file1 ! echo '$''RCSfile$' >> file1 ! echo '$''Revision$' >> file1 ! echo '$''Source$' >> file1 ! echo '$''State$' >> file1 ! echo '$''MyBSD$' >> file1 ! dotest keywordexpand-3 \ ! "${testcvs} -Q import -I ! -m test-import-with-bsd-keyword keywordexpand vendor v1" \ ! '' ! cd .. - dotest keywordexpand-4 "${testcvs} -Q checkout keywordexpand" '' - cd keywordexpand - dotest keywordexpand-5 "cat file1" \ - "\$""Author\$ - \$""Date\$ - \$""CVSHeader\$ - \$""Header\$ - \$""Id\$ - \$""Locker\$ - \$""Log\$ - \$""Name\$ - \$""RCSfile\$ - \$""Revision\$ - \$""Source\$ - \$""State\$ - \$MyBSD\$" - cd ../CVSROOT - # Now expand just the MyBSD and Id keywords - mv config config.old - sed -e 's/KeywordExpand=i/KeywordExpand=iMyBSD,Id/' < config.old > config - rm -f config.old - dotest keywordexpand-6 "${testcvs} -Q ci -mkeywordexpand config" - cd ../keywordexpand - echo 'a change' >> file1 - dotest keywordexpand-7 "${testcvs} -Q ci -madd" - dotest keywordexpand-8 "cat file1" \ - "\$""Author\$ - \$""Date\$ - \$""CVSHeader\$ - \$""Header\$ - \$""Id: file1,v 1\.2 [0-9/]* [0-9:]* ${username} Exp \$ - \$""Locker\$ - \$""Log\$ - \$""Name\$ - \$""RCSfile\$ - \$""Revision\$ - \$""Source\$ - \$""State\$ - \$MyBSD: keywordexpand/file1,v 1\.2 [0-9/]* [0-9:]* ${username} Exp \$ - a change" ! cd ../CVSROOT ! mv config config.old ! sed -e 's/LocalKeyword=MyBSD/LocalKeyword=My_BSD/' \ ! config ! dotest keywordexpand-9 "$testcvs -Q ci -minvalidlocalkeyword config" ! dotest keywordexpand-10 "$testcvs -Q update config" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Bad character \`_' in key \`My_BSD'" ! cp config.old config ! dotest keywordexpand-11 "$testcvs -Q ci -mfixit config" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Bad character \`_' in key \`My_BSD'" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Bad character \`_' in key \`My_BSD' ! $SPROG [a-z]*: $CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Bad character \`_' in key \`My_BSD'" ! dotest keywordexpand-12 "$testcvs -Q update config" ! sed -e 's/LocalKeyword=MyBSD=CVSHeader/LocalKeyword=MyBSD=Name/' \ ! config ! dotest keywordexpand-13 \ ! "$testcvs -Q ci -minvalidlocalkeyword2 config" ! dotest keywordexpand-14 "$testcvs -Q update config" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Unknown LocalId mode: \`Name'" ! cp config.old config ! dotest keywordexpand-15 "$testcvs -Q ci -mfixit2 config" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Unknown LocalId mode: \`Name'" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Unknown LocalId mode: \`Name' ! $SPROG [a-z]*: $CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Unknown LocalId mode: \`Name'" ! dotest keywordexpand-16 "$testcvs -Q update config" dokeep ! # Done. Clean up. ! cd ../.. ! rm -rf $TESTDIR/keywordexpand ! modify_repo rm -rf $CVSROOT_DIRNAME/keywordexpand ! restore_adm ;; --- 12019,14357 ---- "${SPROG} update: \`file1' is no longer in the repository ${SPROG} update: \`file2' is no longer in the repository" ! # OK, now add a directory to both working directories ! # and see that CVS doesn't lose its mind. ! mkdir sdir ! dotest conflicts3-14 "${testcvs} add sdir" \ ! "Directory ${CVSROOT_DIRNAME}/first-dir/sdir added to the repository" ! touch sdir/sfile ! dotest conflicts3-14a "${testcvs} add sdir/sfile" \ ! "${SPROG} add: scheduling file .sdir/sfile. for addition ! ${SPROG} add: use .${SPROG} commit. to add this file permanently" ! dotest conflicts3-14b "${testcvs} -q ci -m add" \ ! "$CVSROOT_DIRNAME/first-dir/sdir/sfile,v <-- sdir/sfile ! initial revision: 1\.1" ! ! cd ../../2/first-dir ! ! # Create a CVS directory without the proper administrative ! # files in it. This can happen for example if you hit ^C ! # in the middle of a checkout. ! mkdir sdir ! mkdir sdir/CVS ! # OK, in the local case CVS sees that the directory exists ! # in the repository and recurses into it. In the remote case ! # CVS can't see the repository and has no way of knowing ! # that sdir is even a directory (stat'ing everything would be ! # too slow). The remote behavior makes more sense to me (but ! # would this affect other cases?). ! if $remote; then ! dotest conflicts3-15 "${testcvs} -q update" \ ! "${QUESTION} sdir" ! else ! dotest conflicts3-15 "${testcvs} -q update" \ ! "${QUESTION} sdir ! ${SPROG} update: ignoring sdir (CVS/Repository missing)" ! touch sdir/CVS/Repository ! dotest conflicts3-16 "${testcvs} -q update" \ ! "${QUESTION} sdir ! ${SPROG} update: ignoring sdir (CVS/Entries missing)" ! cd .. ! dotest conflicts3-16a "${testcvs} -q update first-dir" \ ! "${QUESTION} first-dir/sdir ! ${SPROG} update: ignoring first-dir/sdir (CVS/Entries missing)" ! cd first-dir ! fi ! rm -r sdir ! ! # OK, now the same thing, but the directory doesn't exist ! # in the repository. ! mkdir newdir ! mkdir newdir/CVS ! dotest conflicts3-17 "${testcvs} -q update" "${QUESTION} newdir" ! echo "D/newdir////" >> CVS/Entries ! dotest conflicts3-18 "${testcvs} -q update" \ ! "${CPROG} update: ignoring newdir (CVS/Repository missing)" ! touch newdir/CVS/Repository ! dotest conflicts3-19 "${testcvs} -q update" \ ! "${CPROG} update: ignoring newdir (CVS/Entries missing)" ! cd .. ! dotest conflicts3-20 "${testcvs} -q update first-dir" \ ! "${CPROG} update: ignoring first-dir/newdir (CVS/Entries missing)" ! cd first-dir ! rm -r newdir ! ! # The previous tests have left CVS/Entries in something of a mess. ! # While we "should" be able to deal with that (maybe), for now ! # we just start over. ! cd .. ! rm -r first-dir ! dotest conflicts3-20a "${testcvs} -q co -l first-dir" '' ! cd first-dir ! ! dotest conflicts3-21 "${testcvs} -q update -d sdir" "U sdir/sfile" ! rm -r sdir/CVS ! dotest conflicts3-22 "${testcvs} -q update" "${QUESTION} sdir" ! if $remote; then ! dotest_fail conflicts3-23 "${testcvs} -q update -PdA" \ ! "${QUESTION} sdir ! ${CPROG} update: move away \`sdir/sfile'; it is in the way ! C sdir/sfile" ! else ! dotest conflicts3-23 "${testcvs} -q update -PdA" \ ! "${QUESTION} sdir" ! fi ! ! # Not that it should really affect much, but let's do the case ! # where sfile has been removed. For example, suppose that sdir ! # had been a CVS-controlled directory which was then removed ! # by removing each file (and using update -P or some such). Then ! # suppose that the build process creates an sdir directory which ! # is not supposed to be under CVS. ! rm -r sdir ! dotest conflicts3-24 "${testcvs} -q update -d sdir" "U sdir/sfile" ! rm sdir/sfile ! dotest conflicts3-25 "${testcvs} rm sdir/sfile" \ ! "${SPROG} remove: scheduling .sdir/sfile. for removal ! ${SPROG} remove: use .${SPROG} commit. to remove this file permanently" ! dotest conflicts3-26 "${testcvs} ci -m remove sdir/sfile" \ ! "${CVSROOT_DIRNAME}/first-dir/sdir/sfile,v <-- sdir/sfile ! new revision: delete; previous revision: 1\.1" ! rm -r sdir/CVS ! dotest conflicts3-27 "${testcvs} -q update" "${QUESTION} sdir" ! dotest conflicts3-28 "${testcvs} -q update -PdA" \ ! "${QUESTION} sdir" ! ! dokeep ! cd ../.. ! rm -r 1 2 ! modify_repo rm -rf $CVSROOT_DIRNAME/first-dir ! ;; ! ! ! ! clean) ! # Test update -C (overwrite local mods w/ repository copies) ! mkdir 1; cd 1 ! dotest clean-1 "${testcvs} -q co -l ." '' ! mkdir first-dir ! dotest clean-2 "${testcvs} add first-dir" \ ! "Directory ${CVSROOT_DIRNAME}/first-dir added to the repository" ! cd first-dir ! echo "The usual boring test text." > cleanme.txt ! dotest clean-3 "${testcvs} add cleanme.txt" \ ! "${SPROG} add: scheduling file .cleanme\.txt. for addition ! ${SPROG} add: use .${SPROG} commit. to add this file permanently" ! dotest clean-4 "${testcvs} -q ci -m clean-3" \ ! "$CVSROOT_DIRNAME/first-dir/cleanme\.txt,v <-- cleanme\.txt ! initial revision: 1\.1" ! # Okay, preparation is done, now test. ! # Check that updating an unmodified copy works. ! dotest clean-5 "${testcvs} -q update" '' ! # Check that updating -C an unmodified copy works. ! dotest clean-6 "${testcvs} -q update -C" '' ! # Check that updating a modified copy works. ! echo "fish" >> cleanme.txt ! dotest clean-7 "${testcvs} -q update" 'M cleanme\.txt' ! # Check that updating -C a modified copy works. ! dotest clean-8 "${testcvs} -q update -C" \ ! "(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1) ! U cleanme\.txt" ! # And check that the backup copy really was made. ! dotest clean-9 "cat .#cleanme.txt.1.1" \ ! "The usual boring test text\. ! fish" ! ! # Do it all again, this time naming the file explicitly. ! rm .#cleanme.txt.1.1 ! dotest clean-10 "${testcvs} -q update cleanme.txt" '' ! dotest clean-11 "${testcvs} -q update -C cleanme.txt" '' ! echo "bluegill" >> cleanme.txt ! dotest clean-12 "${testcvs} -q update cleanme.txt" 'M cleanme\.txt' ! dotest clean-13 "${testcvs} -q update -C cleanme.txt" \ ! "(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1) ! U cleanme\.txt" ! # And check that the backup copy really was made. ! dotest clean-14 "cat .#cleanme.txt.1.1" \ ! "The usual boring test text\. ! bluegill" ! ! # Now try with conflicts ! cd .. ! dotest clean-15 "${testcvs} -q co -d second-dir first-dir" \ ! 'U second-dir/cleanme\.txt' ! cd second-dir ! echo "conflict test" >> cleanme.txt ! dotest clean-16 "${testcvs} -q ci -m." \ ! "$CVSROOT_DIRNAME/first-dir/cleanme\.txt,v <-- cleanme\.txt ! new revision: 1\.2; previous revision: 1\.1" ! cd ../first-dir ! echo "fish" >> cleanme.txt ! dotest clean-17 "${testcvs} -nq update" \ ! "RCS file: ${CVSROOT_DIRNAME}/first-dir/cleanme\.txt,v ! retrieving revision 1\.1 ! retrieving revision 1\.2 ! Merging differences between 1\.1 and 1\.2 into cleanme\.txt ! rcsmerge: warning: conflicts during merge ! ${SPROG} update: conflicts found in cleanme\.txt ! C cleanme\.txt" ! dotest clean-18 "${testcvs} -q update -C" \ ! "(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1) ! U cleanme\.txt" ! dotest clean-19 "cat .#cleanme.txt.1.1" \ ! "The usual boring test text\. ! fish" ! ! # Done. Clean up. ! dokeep ! cd ../.. ! rm -rf 1 ! modify_repo rm -rf $CVSROOT_DIRNAME/first-dir ! ;; ! ! ! ! keywordexpand) ! # Tests of the original *BSD tag= and keywordexpand= features ! # are done via the LocalKeyword= and KeywordExpand features. ! ! # Skip this in noredirect mode because it is too easy for the primary ! # and secondary error messages to get out of sync when the ! # CVSROOT/config files are broken. This is intentional, since it is ! # possible and even likely that an administrator might want to set up ! # different configurations on the two servers and the paths to the ! # config files on the secondary and primary were intentionally left ! # intact even though they might be different. ! if $noredirect; then ! notnoredirect keywordexpand ! continue ! fi ! ! mkdir keywordexpand; cd keywordexpand ! ! dotest keywordexpand-1 "${testcvs} -q co CVSROOT" \ ! 'U CVSROOT/checkoutlist ! U CVSROOT/commitinfo ! U CVSROOT/config ! U CVSROOT/cvswrappers ! U CVSROOT/loginfo ! U CVSROOT/modules ! U CVSROOT/notify ! U CVSROOT/postadmin ! U CVSROOT/postproxy ! U CVSROOT/posttag ! U CVSROOT/postwatch ! U CVSROOT/preproxy ! U CVSROOT/rcsinfo ! U CVSROOT/stags ! U CVSROOT/taginfo ! U CVSROOT/verifymsg' ! cd CVSROOT ! echo LocalKeyword=MyBSD=CVSHeader >> config ! # First do not expand any keywords ! echo KeywordExpand=i >> config ! dotest keywordexpand-2 "${testcvs} -Q ci -mkeywordexpand config" ! ! cd .. ! ! mkdir testimport; cd testimport ! echo '$''Author$' > file1 ! echo '$''Date$' >> file1 ! echo '$''CVSHeader$' >> file1 ! echo '$''Header$' >> file1 ! echo '$''Id$' >> file1 ! echo '$''Locker$' >> file1 ! echo '$''Log$' >> file1 ! echo '$''Name$' >> file1 ! echo '$''RCSfile$' >> file1 ! echo '$''Revision$' >> file1 ! echo '$''Source$' >> file1 ! echo '$''State$' >> file1 ! echo '$''MyBSD$' >> file1 ! dotest keywordexpand-3 \ ! "${testcvs} -Q import -I ! -m test-import-with-bsd-keyword keywordexpand vendor v1" \ ! '' ! cd .. ! ! dotest keywordexpand-4 "${testcvs} -Q checkout keywordexpand" '' ! cd keywordexpand ! dotest keywordexpand-5 "cat file1" \ ! "\$""Author\$ ! \$""Date\$ ! \$""CVSHeader\$ ! \$""Header\$ ! \$""Id\$ ! \$""Locker\$ ! \$""Log\$ ! \$""Name\$ ! \$""RCSfile\$ ! \$""Revision\$ ! \$""Source\$ ! \$""State\$ ! \$MyBSD\$" ! cd ../CVSROOT ! # Now expand just the MyBSD and Id keywords ! mv config config.old ! sed -e 's/KeywordExpand=i/KeywordExpand=iMyBSD,Id/' < config.old > config ! rm -f config.old ! dotest keywordexpand-6 "${testcvs} -Q ci -mkeywordexpand config" ! cd ../keywordexpand ! echo 'a change' >> file1 ! dotest keywordexpand-7 "${testcvs} -Q ci -madd" ! dotest keywordexpand-8 "cat file1" \ ! "\$""Author\$ ! \$""Date\$ ! \$""CVSHeader\$ ! \$""Header\$ ! \$""Id: file1,v 1\.2 [0-9/]* [0-9:]* ${username} Exp \$ ! \$""Locker\$ ! \$""Log\$ ! \$""Name\$ ! \$""RCSfile\$ ! \$""Revision\$ ! \$""Source\$ ! \$""State\$ ! \$MyBSD: keywordexpand/file1,v 1\.2 [0-9/]* [0-9:]* ${username} Exp \$ ! a change" ! ! cd ../CVSROOT ! mv config config.old ! sed -e 's/LocalKeyword=MyBSD/LocalKeyword=My_BSD/' \ ! config ! dotest keywordexpand-9 "$testcvs -Q ci -minvalidlocalkeyword config" ! dotest keywordexpand-10 "$testcvs -Q update config" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Bad character \`_' in key \`My_BSD'" ! cp config.old config ! dotest keywordexpand-11 "$testcvs -Q ci -mfixit config" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Bad character \`_' in key \`My_BSD'" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Bad character \`_' in key \`My_BSD' ! $SPROG [a-z]*: $CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Bad character \`_' in key \`My_BSD'" ! dotest keywordexpand-12 "$testcvs -Q update config" ! sed -e 's/LocalKeyword=MyBSD=CVSHeader/LocalKeyword=MyBSD=Name/' \ ! config ! dotest keywordexpand-13 \ ! "$testcvs -Q ci -minvalidlocalkeyword2 config" ! dotest keywordexpand-14 "$testcvs -Q update config" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Unknown LocalId mode: \`Name'" ! cp config.old config ! dotest keywordexpand-15 "$testcvs -Q ci -mfixit2 config" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Unknown LocalId mode: \`Name'" \ ! "$SPROG [a-z]*: $SECONDARY_CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Unknown LocalId mode: \`Name' ! $SPROG [a-z]*: $CVSROOT_DIRNAME/CVSROOT/config \[[1-9][0-9]*\]: LocalKeyword ignored: Unknown LocalId mode: \`Name'" ! dotest keywordexpand-16 "$testcvs -Q update config" ! ! dokeep ! # Done. Clean up. ! cd ../.. ! rm -rf $TESTDIR/keywordexpand ! modify_repo rm -rf $CVSROOT_DIRNAME/keywordexpand ! restore_adm ! ;; ! ! ! ! tag-ext) ! # Test the new tag extensions: ! # .trunk ! # .base ! # .next ! # .prev ! # .root ! # .origin ! save_TZ=$TZ ! TZ=UTC0; export TZ ! module=tag-ext ! mkdir $module; cd $module ! mkdir top; cd top ! dotest tag-ext-init-1 "$testcvs -Q co -l ." ! mkdir tag-ext ! dotest tag-ext-init-1b "$testcvs -Q add tag-ext" ! cd .. ! dotest tag-ext-init-1c "$testcvs -Q co $module" ! cd $module ! echo content >file1 ! echo different content >file2 ! dotest tag-ext-init-2 "$testcvs -Q add file1 file2" ! dotest tag-ext-init-3 "$testcvs -Q ci -madd-em" ! echo content2 >file1 ! echo different content2 >file2 ! dotest tag-ext-init-4 "$testcvs -Q ci -mvers2" ! dotest tag-ext-init-5 "$testcvs -Q tag -b BRANCH1" ! echo content3 >file1 ! echo different content3 >file2 ! dotest tag-ext-init-6 "$testcvs -Q ci -mvers3" ! dotest tag-ext-init-7 "$testcvs -Q tag -b BRANCH2" ! dotest tag-ext-init-8 "$testcvs -Q update -r BRANCH1" ! echo b1content >file3 ! dotest tag-ext-init-9 "$testcvs -Q add file3" ! dotest tag-ext-init-10 "$testcvs -Q ci -maddbranch1" ! dotest tag-ext-init-11 "$testcvs -Q update -r BRANCH2" ! echo b2content >file3 ! dotest tag-ext-init-12 "$testcvs -Q add file3" ! dotest tag-ext-init-13 "$testcvs -Q ci -maddbranch2" ! dotest tag-ext-init-14 "$testcvs -Q update -A" ! echo content >file3 ! dotest tag-ext-init-15 "$testcvs -Q add file3" ! dotest tag-ext-init-16 "$testcvs -Q ci -maddtrunk" ! cd .. ! mkdir import ! cd import ! echo content vicontent >file3 ! dotest tag-ext-init-17 \ ! "$testcvs -Q import -mimportvendor tag-ext VENDOR RELEASE" ! cd .. ! rm -r import ! cd $module ! ! ! ! dotest tag-ext-1 "$testcvs -q log" " ! RCS file: $CVSROOT_DIRNAME/$module/file1,v ! Working file: file1 ! head: 1\.3 ! branch: ! locks: strict ! access list: ! symbolic names: ! BRANCH2: 1\.3\.0\.2 ! BRANCH1: 1\.2\.0\.2 ! keyword substitution: kv ! total revisions: 3; selected revisions: 3 ! description: ! ---------------------------- ! revision 1\.3 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! vers3 ! ---------------------------- ! revision 1\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! vers2 ! ---------------------------- ! revision 1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; commitid: ${commitid}; ! add-em ! ============================================================================= ! ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! Working file: file2 ! head: 1\.3 ! branch: ! locks: strict ! access list: ! symbolic names: ! BRANCH2: 1\.3\.0\.2 ! BRANCH1: 1\.2\.0\.2 ! keyword substitution: kv ! total revisions: 3; selected revisions: 3 ! description: ! ---------------------------- ! revision 1\.3 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! vers3 ! ---------------------------- ! revision 1\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! vers2 ! ---------------------------- ! revision 1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; commitid: ${commitid}; ! add-em ! ============================================================================= ! ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! Working file: file3 ! head: 1\.2 ! branch: ! locks: strict ! access list: ! symbolic names: ! RELEASE: 1\.1\.1\.1 ! VENDOR: 1\.1\.1 ! BRANCH2: 1\.1\.0\.4 ! BRANCH1: 1\.1\.0\.2 ! keyword substitution: kv ! total revisions: 6; selected revisions: 6 ! description: ! ---------------------------- ! revision 1\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! addtrunk ! ---------------------------- ! revision 1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: dead; commitid: ${commitid}; ! branches: 1\.1\.1; 1\.1\.2; 1\.1\.4; ! file file3 was initially added on branch BRANCH1\. ! ---------------------------- ! revision 1\.1\.4\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! addbranch2 ! ---------------------------- ! revision 1\.1\.4\.1 ! date: ${ISO8601DATE}; author: ${username}; state: dead; lines: +0 -0; commitid: ${commitid}; ! file file3 was added on branch BRANCH2 on ${ISO8601DATE} ! ---------------------------- ! revision 1\.1\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! addbranch1 ! ---------------------------- ! revision 1\.1\.1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! importvendor ! =============================================================================" ! ! dotest tag-ext-2 "$testcvs -q update -r.base" ! dotest tag-ext-3 "cat CVS/Entries && cat CVS/Tag" \ ! "/file1/1\.3/[a-zA-Z0-9 :]*//T\.base ! /file2/1\.3/[a-zA-Z0-9 :]*//T\.base ! /file3/1\.2/[a-zA-Z0-9 :]*//T\.base ! D ! T\.base" ! ! dotest tag-ext-4 "$testcvs -q update -r.trunk" ! dotest tag-ext-5 "cat CVS/Entries && cat CVS/Tag" \ ! "/file1/1\.3/[a-zA-Z0-9 :]*//T\.trunk ! /file2/1\.3/[a-zA-Z0-9 :]*//T\.trunk ! /file3/1\.2/[a-zA-Z0-9 :]*//T\.trunk ! D ! T\.trunk" ! ! dotest tag-ext-6 "$testcvs -q update -r.trunk.prev" \ ! "U file1 ! U file2 ! cvs update: \`file3' is no longer in the repository" ! dotest tag-ext-7 "cat CVS/Entries && cat CVS/Tag" \ ! "/file1/1\.2/[a-zA-Z0-9 :]*//T1\.2 ! /file2/1\.2/[a-zA-Z0-9 :]*//T1\.2 ! D ! N\.trunk\.prev" ! ! dotest tag-ext-8 "$testcvs -q update -rBRANCH1" \ ! "U file3" ! dotest tag-ext-9 "cat CVS/Entries && cat CVS/Tag" \ ! "/file1/1\.2/[a-zA-Z0-9 :]*//TBRANCH1 ! /file2/1\.2/[a-zA-Z0-9 :]*//TBRANCH1 ! /file3/1\.1\.2\.1/[a-zA-Z0-9 :]*//TBRANCH1 ! D ! TBRANCH1" ! ! echo b1content >file1 ! echo b1content >file2 ! echo b1content >file3 ! dotest tag-ext-10 "$testcvs -Q ci -maddbranch1" ! dotest tag-ext-12 "$testcvs -Q tag -b BRANCH1-1" ! echo b1content2 >file1 ! echo b1content2 >file2 ! echo b1content2 >file3 ! dotest tag-ext-13 "$testcvs -Q ci -maddbranch1" ! dotest tag-ext-14 "$testcvs -q update -rBRANCH1-1" \ ! "U file1 ! U file2 ! U file3" ! echo b1-1content >file1 ! echo b1-1content >file2 ! echo b1-1content >file3 ! dotest tag-ext-15 "$testcvs -Q ci -maddbranch1-1" ! echo b1-1content2 >file1 ! echo b1-1content2 >file2 ! echo b1-1content2 >file3 ! dotest tag-ext-16 "$testcvs -Q ci -maddbranch1-1" ! dotest tag-ext-17 "cat CVS/Entries && cat CVS/Tag" \ ! "/file1/1\.2\.2\.1\.2\.2/[a-zA-Z0-9 :]*//TBRANCH1-1 ! /file2/1\.2\.2\.1\.2\.2/[a-zA-Z0-9 :]*//TBRANCH1-1 ! /file3/1\.1\.2\.1\.2\.2/[a-zA-Z0-9 :]*//TBRANCH1-1 ! D ! TBRANCH1-1" ! ! dotest_fail tag-ext-18 "$testcvs -Q -n diff -r \.prev" \ ! "${SPROG} \[diff aborted\]: Tag .\.prev. invalid\. Tag must not be relative: .\.prev." ! ! dotest_fail tag-ext-19 "$testcvs diff -r \.prev file2 file3" \ ! "Index: file2 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! retrieving revision 1\.2\.2\.1\.2\.1 ! retrieving revision 1\.2\.2\.1\.2\.2 ! diff -r1\.2\.2\.1\.2\.1 -r1\.2\.2\.1\.2\.2 ! 1c1 ! < b1-1content ! --- ! > b1-1content2 ! Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.1\.2\.1 ! retrieving revision 1\.1\.2\.1\.2\.2 ! diff -r1\.1\.2\.1\.2\.1 -r1\.1\.2\.1\.2\.2 ! 1c1 ! < b1-1content ! --- ! > b1-1content2" ! ! dotest_fail tag-ext-20 "$testcvs diff -r \.root file2 file3" \ ! "Index: file2 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! retrieving revision 1\.2\.2\.1 ! retrieving revision 1\.2\.2\.1\.2\.2 ! diff -r1\.2\.2\.1 -r1\.2\.2\.1\.2\.2 ! 1c1 ! < b1content ! --- ! > b1-1content2 ! Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.1 ! retrieving revision 1\.1\.2\.1\.2\.2 ! diff -r1\.1\.2\.1 -r1\.1\.2\.1\.2\.2 ! 1c1 ! < b1content ! --- ! > b1-1content2" ! ! dotest_fail tag-ext-21 "$testcvs diff -r \.root.root file2 file3" \ ! "Index: file2 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! retrieving revision 1\.2 ! retrieving revision 1\.2\.2\.1\.2\.2 ! diff -r1\.2 -r1\.2\.2\.1\.2\.2 ! 1c1 ! < different content2 ! --- ! > b1-1content2 ! ${SPROG} diff: Tag \.root\.root refers to a dead (removed) revision in file .file3.\. ! cvs diff: No comparison available\. Pass .-N. to .${SPROG} diff.${QUESTION}" ! ! dotest_fail tag-ext-22 "$testcvs diff -r \.origin file2 file3" \ ! "Index: file2 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! retrieving revision 1\.1 ! retrieving revision 1\.2\.2\.1\.2\.2 ! diff -r1\.1 -r1\.2\.2\.1\.2\.2 ! 1c1 ! < different content ! --- ! > b1-1content2 ! Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.1 ! retrieving revision 1\.1\.2\.1\.2\.2 ! diff -r1\.1\.2\.1 -r1\.1\.2\.1\.2\.2 ! 1c1 ! < b1content ! --- ! > b1-1content2" ! ! dotest_fail tag-ext-23 "$testcvs diff -r \.origin.head file2 file3" \ ! "Index: file2 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! retrieving revision 1\.3 ! retrieving revision 1\.2\.2\.1\.2\.2 ! diff -r1\.3 -r1\.2\.2\.1\.2\.2 ! 1c1 ! < different content3 ! --- ! > b1-1content2 ! Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.2 ! retrieving revision 1\.1\.2\.1\.2\.2 ! diff -r1\.1\.2\.2 -r1\.1\.2\.1\.2\.2 ! 1c1 ! < b1content2 ! --- ! > b1-1content2" ! ! dotest tag-ext-24 "$testcvs -q update -r\.trunk" \ ! "U file1 ! U file2 ! U file3" ! ! echo tcontent >file3 ! dotest tag-ext-25 "$testcvs -Q ci -maddtrunk" ! ! dotest_fail tag-ext-26 "$testcvs -Q -n diff -r \.prev" \ ! "${SPROG} \[diff aborted\]: Tag .\.prev. invalid\. Tag must not be relative: .\.prev." ! ! echo tcontent >file4 ! dotest tag-ext-27 "$testcvs -Q add file4" ! ! dotest tag-ext-28 "$testcvs -Q ci -maddtrunk" ! ! rm file4 ! dotest tag-ext-29 "$testcvs remove file4" \ ! "cvs remove: scheduling \`file4' for removal ! cvs remove: use \`cvs commit' to remove this file permanently" ! ! dotest tag-ext-30 "$testcvs -Q ci -mremtrunk" ! ! dotest_fail tag-ext-31 "$testcvs diff -r \.prev file2 file3" \ ! "Index: file2 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! retrieving revision 1\.2 ! retrieving revision 1\.3 ! diff -r1\.2 -r1\.3 ! 1c1 ! < different content2 ! --- ! > different content3 ! Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.2 ! retrieving revision 1\.3 ! diff -r1\.2 -r1\.3 ! 1c1 ! < content ! --- ! > tcontent" ! ! dotest_fail tag-ext-32 "$testcvs diff -r \.root file2 file3" \ ! "cvs diff: tag \.root is not in file file2 ! cvs diff: tag \.root is not in file file3" ! ! dotest tag-ext-33 "$testcvs diff -r \.origin.head file2 file3" ! ! dotest_fail tag-ext-34 "$testcvs diff -r BRANCH1-1\.root file2 file3" \ ! "Index: file2 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! retrieving revision 1\.2\.2\.1 ! retrieving revision 1\.3 ! diff -r1\.2\.2\.1 -r1\.3 ! 1c1 ! < b1content ! --- ! > different content3 ! Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.1 ! retrieving revision 1\.3 ! diff -r1\.1\.2\.1 -r1\.3 ! 1c1 ! < b1content ! --- ! > tcontent" ! ! dotest_fail tag-ext-35 "$testcvs diff -r BRANCH1-1\.root\.prev\.head file2 file3" \ ! "cvs diff: tag BRANCH1-1\.root\.prev\.head is not in file file3" ! ! dotest tag-ext-36 "$testcvs -q update -r BRANCH1 file3" \ ! "U file3" ! ! dotest tag-ext-37 "$testcvs tag -b BRANCH1-2 file3" \ ! "T file3" ! ! echo b1content3 >file3 ! dotest tag-ext-38 "$testcvs -Q ci -maddbranch1 file3" ! ! dotest tag-ext-39 "$testcvs -q update -r BRANCH1-2 file3" \ ! "U file3" ! ! echo b1-2content1 >file3 ! dotest tag-ext-40 "$testcvs -Q ci -maddbranch1-2.1 file3" ! ! echo b1-2content2 >file3 ! dotest tag-ext-41 "$testcvs -Q ci -maddbranch1-2.2 file3" ! ! dotest tag-ext-42 "$testcvs tag -b BRANCH1-2-1 file3" \ ! "T file3" ! ! echo b1-2content3 >file3 ! dotest tag-ext-43 "$testcvs -Q ci -maddbranch1-2.3 file3" ! ! dotest tag-ext-44 "$testcvs -q update -r BRANCH1-2-1 file3" \ ! "U file3" ! ! echo b1-2-1content1 >file3 ! dotest tag-ext-45 "$testcvs -Q ci -maddbranch1-2-1.1 file3" ! ! echo b1-2-1content2 >file3 ! dotest tag-ext-46 "$testcvs -Q ci -maddbranch1-2-1.2 file3" ! ! ! echo b1-2-1content3 >file3 ! dotest tag-ext-47 "$testcvs -Q ci -maddbranch1-2-1.3 file3" ! ! echo b1-2-1content4 >file3 ! dotest tag-ext-48 "$testcvs -Q ci -maddbranch1-2-1.4 file3" ! ! echo b1-2-1content5 >file3 ! dotest tag-ext-49 "$testcvs -Q ci -maddbranch1-2-1.5 file3" ! ! echo b1-2-1content6 >file3 ! dotest tag-ext-50 "$testcvs -Q ci -maddbranch1-2-1.6 file3" ! ! echo b1-2-1content7 >file3 ! dotest tag-ext-51 "$testcvs -Q ci -maddbranch1-2-1.7 file3" ! ! echo b1-2-1content8 >file3 ! dotest tag-ext-52 "$testcvs -Q ci -maddbranch1-2-1.8 file3" ! ! echo b1-2-1content9 >file3 ! dotest tag-ext-53 "$testcvs -Q ci -maddbranch1-2-1.9 file3" ! ! dotest tag-ext-54 "$testcvs tag -b BRANCH1-2-1-1 file3" \ ! "T file3" ! ! echo b1-2-1content10 >file3 ! dotest tag-ext-55 "$testcvs -Q ci -maddbranch1-2-1.10 file3" ! ! rm file3 ! dotest tag-ext-56 "$testcvs remove file3" \ ! "cvs remove: scheduling \`file3' for removal ! cvs remove: use \`cvs commit' to remove this file permanently" ! ! dotest tag-ext-57 "$testcvs -Q ci -mremBRANCH1-2-1.11 file3" ! ! dotest tag-ext-58 "$testcvs -q update -r BRANCH1-2-1-1 file3" \ ! "U file3" ! ! echo b1-2-1-1content1 >file3 ! dotest tag-ext-59 "$testcvs -Q ci -maddbranch1-2-1-1.1 file3" ! ! echo b1-2-1-1content2 >file3 ! dotest tag-ext-60 "$testcvs -Q ci -maddbranch1-2-1-1.2 file3" ! ! dotest tag-ext-61 "$testcvs tag -b BRANCH1-2-1-1-1-1 file3" \ ! "T file3" ! ! echo b1-2-1-1content3 >file3 ! dotest tag-ext-62 "$testcvs -Q ci -maddbranch1-2-1-1.3 file3" ! ! dotest tag-ext-63 "$testcvs admin -o 1.1.2.2.2.2.2.4::1.1.2.2.2.2.2.8 file3" \ ! "RCS file: $CVSROOT_DIRNAME/$module/file3,v ! deleting revision 1\.1\.2\.2\.2\.2\.2\.5 ! deleting revision 1\.1\.2\.2\.2\.2\.2\.6 ! deleting revision 1\.1\.2\.2\.2\.2\.2\.7 ! done" ! ! dotest tag-ext-64 "$testcvs admin -o 1.1.2.2.2.2.2.2::1.1.2.2.2.2.2.4 file3" \ ! "RCS file: $CVSROOT_DIRNAME/$module/file3,v ! deleting revision 1\.1\.2\.2\.2\.2\.2\.3 ! done" ! ! dotest_fail tag-ext-65 "$testcvs diff -r \.root\.root\.root\.head file3" \ ! "Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.3 ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! diff -r1\.1\.2\.3 -r1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! 1c1 ! < b1content3 ! --- ! > b1-2-1-1content3" ! ! dotest_fail tag-ext-66 "$testcvs diff -r \.origin -r \.origin\.head file3" \ ! "Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.1 ! retrieving revision 1\.1\.2\.3 ! diff -r1\.1\.2\.1 -r1\.1\.2\.3 ! 1c1 ! < b1content ! --- ! > b1content3" ! ! dotest tag-ext-67 "$testcvs diff -r \.origin\.prev -r \.root\.head file3" ! ! dotest_fail tag-ext-68 "$testcvs diff -r \.origin\.prev -r \.root file3" \ ! "cvs diff: tag \.origin\.prev is not in file file3" ! ! dotest_fail tag-ext-69 "$testcvs diff -r \.origin -r \.root\.head file3" \ ! "cvs diff: Tag \.root\.head refers to a dead (removed) revision in file \`file3'\. ! cvs diff: No comparison available\. Pass \`-N' to \`cvs diff'?" ! ! dotest_fail tag-ext-70 "$testcvs diff -r \.prev\.prev\.prev\.prev\.prev\.prev\.prev\.prev\.prev\.prev\.prev file3" \ ! "Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.1 ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! diff -r1\.1\.2\.1 -r1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! 1c1 ! < b1content ! --- ! > b1-2-1-1content3" ! ! date_T1=`getrlogdate -r1\.2 tag-ext/file3` ! date_T2=`getrlogdate -r1\.1\.2\.2\.2\.2\.2\.8 tag-ext/file3` ! ! dotest_fail tag-ext-71 "$testcvs diff -r \.trunk:'$date_T1' file3" \ ! "Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.2 ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! diff -r1\.2 -r1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! 1c1 ! < content ! --- ! > b1-2-1-1content3" ! ! dotest_fail tag-ext-72 "$testcvs diff -r BRANCH1-2-1:'$date_T2' file3" \ ! "Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.8 ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! diff -r1\.1\.2\.2\.2\.2\.2\.8 -r1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! 1c1 ! < b1-2-1content8 ! --- ! > b1-2-1-1content3" ! ! dotest_fail tag-ext-73 "$testcvs diff -rBRANCH1.prev file1" \ ! "Index: file1 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file1,v ! retrieving revision 1\.2\.2\.1 ! retrieving revision 1\.3 ! diff -r1\.2\.2\.1 -r1\.3 ! 1c1 ! < b1content ! --- ! > content3" ! ! COMMITID=$(cat $CVSROOT_DIRNAME/tag-ext/file3,v | grep -m 21 commitid | tail -n 1); ! COMMITID=`expr match ${COMMITID:9} '\([a-zA-Z0-9]*\)'` ! dotest_fail tag-ext-74 "$testcvs diff -r .commitid.$COMMITID file3" \ ! "Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.2 ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! diff -r1\.1\.2\.2\.2\.2\.2\.9\.2\.2 -r1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! 1c1 ! < b1-2-1-1content2 ! --- ! > b1-2-1-1content3" ! ! dotest_fail tag-ext-75 "$testcvs diff -r @$COMMITID file3" \ ! "Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.2 ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! diff -r1\.1\.2\.2\.2\.2\.2\.9\.2\.2 -r1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! 1c1 ! < b1-2-1-1content2 ! --- ! > b1-2-1-1content3" ! ! dotest_fail tag-ext-76 "$testcvs diff -r '@<$COMMITID' file3" \ ! "Index: file3 ! =================================================================== ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.1 ! retrieving revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! diff -r1\.1\.2\.2\.2\.2\.2\.9\.2\.1 -r1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! 1c1 ! < b1-2-1-1content1 ! --- ! > b1-2-1-1content3" ! ! COMMITID=$(cat $CVSROOT_DIRNAME/tag-ext/file1,v | grep -m 3 commitid | tail -n 1); ! COMMITID=`expr match ${COMMITID:9} '\([a-zA-Z0-9]*\)'` ! dotest tag-ext-77 "$testcvs update -r .commitid.$COMMITID" \ ! "cvs update: Updating . ! U file1 ! U file2 ! cvs update: \`file3' is no longer in the repository" ! ! dotest tag-ext-78 "cat CVS/Entries && cat CVS/Tag" \ ! "/file1/1\.1/[a-zA-Z0-9 :]*//T\.commitid\.$COMMITID ! /file2/1\.1/[a-zA-Z0-9 :]*//T\.commitid\.$COMMITID ! D ! N\.commitid\.$COMMITID" ! ! dotest tag-ext-79 "$testcvs update -r @$COMMITID" \ ! "cvs update: Updating ." ! ! dotest tag-ext-80 "cat CVS/Entries && cat CVS/Tag" \ ! "/file1/1\.1/[a-zA-Z0-9 :]*//T@$COMMITID ! /file2/1\.1/[a-zA-Z0-9 :]*//T@$COMMITID ! D ! N@$COMMITID" ! ! dotest tag-ext-81 "$testcvs -Q update -r BRANCH1-1" ! ! dotest tag-ext-82 "$testcvs -Q update -r BRANCH1 file1" ! ! COMMITID=$(cat $CVSROOT_DIRNAME/tag-ext/file3,v | grep -m 3 commitid | tail -n 1); ! COMMITID=`expr match ${COMMITID:9} '\([a-zA-Z0-9]*\)'` ! dotest_fail tag-ext-83 "$testcvs diff -r .commitid.$COMMITID" \ ! "cvs diff: Diffing . ! cvs diff: tag .commitid.$COMMITID is not in file file1 ! cvs diff: tag .commitid.$COMMITID is not in file file2 ! Index: file3 ! =================================================================== ! RCS file: /tmp/cvs-sanity/cvsroot/tag-ext/file3,v ! retrieving revision 1\.1\.2\.1 ! retrieving revision 1\.1\.2\.1\.2\.2 ! diff -r1\.1\.2\.1 -r1\.1\.2\.1\.2\.2 ! 1c1 ! < b1content ! --- ! > b1-1content2" ! ! dotest_fail tag-ext-84 "$testcvs diff -r '@<$COMMITID'" \ ! "cvs diff: Diffing . ! cvs diff: tag @<$COMMITID is not in file file1 ! cvs diff: tag @<$COMMITID is not in file file2 ! cvs diff: tag @<$COMMITID is not in file file3" ! ! COMMITID=$(cat $CVSROOT_DIRNAME/tag-ext/file3,v | grep -m 2 commitid | tail -n 1); ! COMMITID=`expr match ${COMMITID:9} '\([a-zA-Z0-9]*\)'` ! dotest_fail tag-ext-85 "$testcvs diff -r '@<$COMMITID'" \ ! "cvs diff: Diffing . ! cvs diff: tag @<$COMMITID is not in file file1 ! cvs diff: tag @<$COMMITID is not in file file2 ! Index: file3 ! =================================================================== ! RCS file: /tmp/cvs-sanity/cvsroot/tag-ext/file3,v ! retrieving revision 1\.1\.2\.1 ! retrieving revision 1\.1\.2\.1\.2\.2 ! diff -r1\.1\.2\.1 -r1\.1\.2\.1\.2\.2 ! 1c1 ! < b1content ! --- ! > b1-1content2" ! ! dotest tag-ext-86 "$testcvs update -j .origin -j .prev file1 file2 file3" \ ! "RCS file: /tmp/cvs-sanity/cvsroot/tag-ext/file1,v ! retrieving revision 1\.1 ! retrieving revision 1\.2\.2\.1 ! Merging differences between 1\.1 and 1\.2\.2\.1 into file1 ! rcsmerge: warning: conflicts during merge ! RCS file: /tmp/cvs-sanity/cvsroot/tag-ext/file2,v ! retrieving revision 1\.1 ! retrieving revision 1\.2\.2\.1\.2\.1 ! Merging differences between 1\.1 and 1\.2\.2\.1\.2\.1 into file2 ! rcsmerge: warning: conflicts during merge ! RCS file: /tmp/cvs-sanity/cvsroot/tag-ext/file3,v ! retrieving revision 1\.1\.2\.1 ! retrieving revision 1\.1\.2\.1\.2\.1 ! Merging differences between 1\.1\.2\.1 and 1\.1\.2\.1\.2\.1 into file3 ! rcsmerge: warning: conflicts during merge" ! ! dotest tag-ext-87 "cat CVS/Entries && cat CVS/Tag" \ ! "/file1/1\.2\.2\.2/Result of merge+[a-zA-Z0-9 :]*//TBRANCH1 ! /file2/1\.2\.2\.1\.2\.2/Result of merge+[a-zA-Z0-9 :]*//TBRANCH1-1 ! /file3/1\.1\.2\.1\.2\.2/Result of merge+[a-zA-Z0-9 :]*//TBRANCH1-1 ! D ! TBRANCH1-1" ! ! dotest tag-ext-88 "$testcvs tag -r .prev atag file1 file2 file3" \ ! "T file1 ! T file2 ! T file3" ! ! dotest tag-ext-89 "$testcvs rtag -r BRANCH1-1.root.next btag tag-ext" \ ! "cvs rtag: Tagging tag-ext" ! ! dotest tag-ext-90 "$testcvs rlog tag-ext" \ ! "cvs rlog: Logging tag-ext ! ! RCS file: $CVSROOT_DIRNAME/$module/file1,v ! head: 1\.3 ! branch: ! locks: strict ! access list: ! symbolic names: ! btag: 1\.2\.2\.2 ! atag: 1\.2\.2\.1 ! BRANCH1-1: 1\.2\.2\.1\.0\.2 ! BRANCH2: 1\.3\.0\.2 ! BRANCH1: 1\.2\.0\.2 ! keyword substitution: kv ! total revisions: 7; selected revisions: 7 ! description: ! ---------------------------- ! revision 1\.3 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! vers3 ! ---------------------------- ! revision 1\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! branches: 1\.2\.2; ! vers2 ! ---------------------------- ! revision 1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; commitid: ${commitid}; ! add-em ! ---------------------------- ! revision 1\.2\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1 ! ---------------------------- ! revision 1\.2\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! branches: 1\.2\.2\.1\.2; ! addbranch1 ! ---------------------------- ! revision 1\.2\.2\.1\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-1 ! ---------------------------- ! revision 1\.2\.2\.1\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-1 ! ============================================================================= ! ! RCS file: $CVSROOT_DIRNAME/$module/file2,v ! head: 1\.3 ! branch: ! locks: strict ! access list: ! symbolic names: ! btag: 1\.2\.2\.2 ! atag: 1\.2\.2\.1\.2\.1 ! BRANCH1-1: 1\.2\.2\.1\.0\.2 ! BRANCH2: 1\.3\.0\.2 ! BRANCH1: 1\.2\.0\.2 ! keyword substitution: kv ! total revisions: 7; selected revisions: 7 ! description: ! ---------------------------- ! revision 1\.3 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! vers3 ! ---------------------------- ! revision 1\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! branches: 1\.2\.2; ! vers2 ! ---------------------------- ! revision 1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; commitid: ${commitid}; ! add-em ! ---------------------------- ! revision 1\.2\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1 ! ---------------------------- ! revision 1\.2\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! branches: 1\.2\.2\.1\.2; ! addbranch1 ! ---------------------------- ! revision 1\.2\.2\.1\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-1 ! ---------------------------- ! revision 1\.2\.2\.1\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-1 ! ============================================================================= ! ! RCS file: $CVSROOT_DIRNAME/$module/file3,v ! head: 1\.3 ! branch: ! locks: strict ! access list: ! symbolic names: ! btag: 1\.1\.2\.2 ! atag: 1\.1\.2\.1\.2\.1 ! BRANCH1-2-1-1-1-1: 1\.1\.2\.2\.2\.2\.2\.9\.2\.2\.0\.2 ! BRANCH1-2-1-1: 1\.1\.2\.2\.2\.2\.2\.9\.0\.2 ! BRANCH1-2-1: 1\.1\.2\.2\.2\.2\.0\.2 ! BRANCH1-2: 1\.1\.2\.2\.0\.2 ! BRANCH1-1: 1\.1\.2\.1\.0\.2 ! RELEASE: 1\.1\.1\.1 ! VENDOR: 1\.1\.1 ! BRANCH2: 1\.1\.0\.4 ! BRANCH1: 1\.1\.0\.2 ! keyword substitution: kv ! total revisions: 24; selected revisions: 24 ! description: ! ---------------------------- ! revision 1\.3 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addtrunk ! ---------------------------- ! revision 1\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! addtrunk ! ---------------------------- ! revision 1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: dead; commitid: ${commitid}; ! branches: 1\.1\.1; 1\.1\.2; 1\.1\.4; ! file file3 was initially added on branch BRANCH1\. ! ---------------------------- ! revision 1\.1\.4\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! addbranch2 ! ---------------------------- ! revision 1\.1\.4\.1 ! date: ${ISO8601DATE}; author: ${username}; state: dead; lines: +0 -0; commitid: ${commitid}; ! file file3 was added on branch BRANCH2 on ${ISO8601DATE} ! ---------------------------- ! revision 1\.1\.2\.3 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1 ! ---------------------------- ! revision 1\.1\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! branches: 1\.1\.2\.2\.2; ! addbranch1 ! ---------------------------- ! revision 1\.1\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! branches: 1\.1\.2\.1\.2; ! addbranch1 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.3 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2\.3 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! branches: 1\.1\.2\.2\.2\.2\.2; ! addbranch1-2\.2 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2\.1 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.11 ! date: ${ISO8601DATE}; author: ${username}; state: dead; lines: +0 -0; commitid: ${commitid}; ! remBRANCH1-2-1\.11 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.10 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2-1\.10 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.9 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! branches: 1\.1\.2\.2\.2\.2\.2\.9\.2; ! addbranch1-2-1\.9 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.8 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2-1\.8 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.4 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2-1\.4 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2-1\.2 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2-1\.1 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.3 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2-1-1\.3 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2-1-1\.2 ! ---------------------------- ! revision 1\.1\.2\.2\.2\.2\.2\.9\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-2-1-1\.1 ! ---------------------------- ! revision 1\.1\.2\.1\.2\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-1 ! ---------------------------- ! revision 1\.1\.2\.1\.2\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -1; commitid: ${commitid}; ! addbranch1-1 ! ---------------------------- ! revision 1\.1\.1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! importvendor ! ============================================================================= ! ! RCS file: $CVSROOT_DIRNAME/$module/Attic/file4,v ! head: 1\.3 ! branch: ! locks: strict ! access list: ! symbolic names: ! keyword substitution: kv ! total revisions: 3; selected revisions: 3 ! description: ! ---------------------------- ! revision 1\.3 ! date: ${ISO8601DATE}; author: ${username}; state: dead; lines: +0 -0; commitid: ${commitid}; ! remtrunk ! ---------------------------- ! revision 1\.2 ! date: ${ISO8601DATE}; author: ${username}; state: Exp; lines: +1 -0; commitid: ${commitid}; ! addtrunk ! ---------------------------- ! revision 1\.1 ! date: ${ISO8601DATE}; author: ${username}; state: dead; commitid: ${commitid}; ! file file4 was initially added on branch \.trunk\. ! =============================================================================" ! ! # clean up ! dokeep ! restore_adm ! cd ../.. ! rm -r $module ! modify_repo rm -rf $CVSROOT_DIRNAME/tag-ext ! TZ=$save_TZ ! ;; ! ! ! soft-tags) ! # check all aspects of soft tags behavior ! ! # prepare the tests ! rm -rf $CVSROOT_DIRNAME/CVSROOT ! dotest soft-tags-0 "${testcvs} -d $CVSROOT_DIRNAME init" ! ! # Save the timezone and set it to UTC for these tests to make the ! # value more predicatable. ! save_TZ=$TZ ! TZ=UTC0; export TZ ! ! modify_repo mkdir $CVSROOT_DIRNAME/first-dir ! modify_repo mkdir $CVSROOT_DIRNAME/first-dir/d1 ! ! # since this test is very dependent on revision dates, I import RCS ! # files by copying its contents directly into the repository. this ! # was based on the 'rcs' test. ! cat <$TESTDIR/f1,v ! head 1.3; ! access; ! symbols ! sb4:1.2.2.3.0.2 ! t2:1.3 ! b1:1.2.0.2 ! t1:1.1; ! locks; strict; ! comment @# @; ! ! ! 1.3 ! date 2007.06.12.04.00.00; author yarony; state Exp; ! branches; ! next 1.2; ! commitid uDB8WIFS65PQFBls; ! ! 1.2 ! date 2007.06.12.02.00.00; author yarony; state Exp; ! branches ! 1.2.2.1; ! next 1.1; ! commitid RaWghsvxA0ZLFBls; ! ! 1.1 ! date 2007.06.12.00.00.00; author yarony; state Exp; ! branches; ! next ; ! commitid kFlVg3SHbMBFuBls; ! ! 1.2.2.1 ! date 2007.06.12.05.00.00; author yarony; state Exp; ! branches; ! next 1.2.2.2; ! commitid HVXipEZ8KEkOKBls; ! ! 1.2.2.2 ! date 2007.06.12.06.00.00; author yarony; state Exp; ! branches; ! next 1.2.2.3; ! commitid rpQKSr7khBbUKBls; ! ! 1.2.2.3 ! date 2007.06.12.08.00.00; author yarony; state Exp; ! branches ! 1.2.2.3.2.1; ! next 1.2.2.4; ! commitid 0qQEytdbcsB3LBls; ! ! 1.2.2.4 ! date 2007.06.12.15.00.00; author yarony; state Exp; ! branches; ! next 1.2.2.5; ! commitid XBr2JAgt2HmhoDls; ! ! 1.2.2.5 ! date 2007.06.12.18.00.00; author yarony; state Exp; ! branches; ! next ; ! commitid 5Ztnt7z1XOZFoDls; ! ! 1.2.2.3.2.1 ! date 2007.06.12.17.00.00; author yarony; state Exp; ! branches; ! next ; ! commitid Xx4hKh8Mda9n5Fms; ! ! ! desc ! @@ ! ! ! 1.3 ! log ! @t3 ! @ ! text ! @3t ! @ ! ! ! 1.2 ! log ! @t2 ! @ ! text ! @d1 1 ! a1 1 ! 2t ! @ ! ! ! 1.2.2.1 ! log ! @1b ! @ ! text ! @d1 1 ! a1 1 ! 1b ! @ ! ! ! 1.2.2.2 ! log ! @2b ! @ ! text ! @d1 1 ! a1 1 ! 2b ! @ ! ! ! 1.2.2.3 ! log ! @3b ! @ ! text ! @a0 1 ! 3b ! a1 1 ! 3b ! @ ! ! ! 1.2.2.3.2.1 ! log ! @branch sb4 - change 1 ! @ ! text ! @a3 3 ! f1b4 ! b5 ! branch sb4 - change 1 ! @ ! ! ! 1.2.2.4 ! log ! @branch_commit_4 ! @ ! text ! @a3 1 ! f1b4 ! @ ! ! ! 1.2.2.5 ! log ! @branch_commit_4 ! @ ! text ! @a4 1 ! b5 ! @ ! ! ! 1.1 ! log ! @t1 ! @ ! text ! @d1 1 ! a1 1 ! 1t ! @ ! ! EOF ! ! cat <$TESTDIR/f2,v ! head 1.4; ! access; ! symbols ! sb5:1.3.2.2.0.4 ! sb4:1.3.2.2.0.2 ! t2:1.4 ! b1:1.3.0.2; ! locks; strict; ! comment @# @; ! ! ! 1.4 ! date 2007.06.12.12.00.00; author yarony; state Exp; ! branches; ! next 1.3; ! commitid cSaXcc1bdE0anDls; ! ! 1.3 ! date 2007.06.12.11.00.00; author yarony; state Exp; ! branches ! 1.3.2.1; ! next 1.2; ! commitid FXKdQ1JhTCW5nDls; ! ! 1.2 ! date 2007.06.12.10.00.00; author yarony; state Exp; ! branches; ! next 1.1; ! commitid t8von72d0WK1nDls; ! ! 1.1 ! date 2007.06.12.09.00.00; author yarony; state Exp; ! branches; ! next ; ! commitid o0BCanMojdvzmDls; ! ! 1.3.2.1 ! date 2007.06.12.13.00.00; author yarony; state Exp; ! branches; ! next 1.3.2.2; ! commitid ScyWOOIPTVEMnDls; ! ! 1.3.2.2 ! date 2007.06.12.14.00.00; author yarony; state Exp; ! branches; ! next 1.3.2.3; ! commitid EDMe6I7RGHCVnDls; ! ! 1.3.2.3 ! date 2007.06.12.16.00.00; author yarony; state Exp; ! branches; ! next 1.3.2.4; ! commitid XBr2JAgt2HmhoDls; ! ! 1.3.2.4 ! date 2007.06.12.18.00.00; author yarony; state Exp; ! branches; ! next ; ! commitid 5Ztnt7z1XOZFoDls; ! ! ! desc ! @@ ! ! ! 1.4 ! log ! @f2t4 ! @ ! text ! @f2t1 ! f2t2 ! f2t3 ! f2t4 ! @ ! ! ! 1.3 ! log ! @f2t3 ! @ ! text ! @d4 1 ! @ ! ! ! 1.3.2.1 ! log ! @f2b1 ! @ ! text ! @a3 1 ! f2b1 ! @ ! ! ! 1.3.2.2 ! log ! @f2b2 ! @ ! text ! @a4 1 ! f2b2 ! @ ! ! ! 1.3.2.3 ! log ! @branch_commit_4 ! @ ! text ! @a5 1 ! f2b4 ! @ ! ! ! 1.3.2.4 ! log ! @branch_commit_4 ! @ ! text ! @a6 1 ! b5 ! @ ! ! ! 1.2 ! log ! @f2t2 ! @ ! text ! @d3 1 ! @ ! ! ! 1.1 ! log ! @f2t1 ! @ ! text ! @d2 1 ! @ ! ! EOF ! ! cp $TESTDIR/f1,v $TESTDIR/f1,v-a ! modify_repo mv $TESTDIR/f1,v $CVSROOT_DIRNAME/first-dir/ ! modify_repo mv $TESTDIR/f2,v $CVSROOT_DIRNAME/first-dir/ ! modify_repo mv $TESTDIR/f1,v-a $CVSROOT_DIRNAME/first-dir/d1/f1,v ! ! mkdir 1; cd 1 ! dotest soft-tags-1-a "$testcvs -Q co CVSROOT first-dir" "" ! cd CVSROOT ! cat >> stags <st2 ! T st6 stXX first-dir # test 6: aliasing to non-existent tag: no files should be included ! T st7 st5 first-dir # test 7: hard<->soft tag conflicts ! T st9 1:2007.06.12.03.00.00 first-dir # test 9: branch+date with branch=trunk, some ! T st10 1:2007.06.12.19.00.00 first-dir # test 10: branch+date with branch=trunk, all ! B sb1 1:2007.06.12.01.00.00 first-dir # test 11: hard-tagging a soft branch ! B sb2 1:2007.06.12.19.00.00 first-dir # test 13: soft branch on trunk+date, all ! # test 14: soft-branch sb3 (b+d) on soft-branch sb2 (b+d), ! # where sb2 doesn't have any real versions on it yet ! B sb3 sb2:2007.06.12.22.00.00 first-dir ! B sb4 b1:2007.06.12.20.00.00 first-dir ! B sb5 b1:2007.06.12.21.00.00 first-dir # tests hard<->soft branch conflicts ! B sb6 b1:2007.06.12.21.00.00 first-dir # test 22: remove on branch with no revisions ! B sb7 b1:2007.06.12.07.00.00 first-dir/d1 # test 25: update with repository set to subdir ! EOF ! # first-dir/f1,v revisions: ! # 1.1 2007-06-12 09:18:24 t1 hard, st4, sb1 ! # XXX change date to 2007-01-01 01:00:00 ! # 1.2 2007-06-12 09:50:46 st9 ! # 1.2.2 branch b1 ! # 1.3 2007-06-12 09:51:00 t2 hard, st3, st10, sb2, sb3 ! # st7 hard runtime ! # 1.2.2.1 2007-06-12 10:05:27 ! # 1.2.2.2 2007-06-12 10:05:43 st1 ! # 1.2.2.3 2007-06-12 10:06:10 ! # 1.2.2.3.2 branch sb4 ! # 1.2.2.3.2.1 2007-06-12 15:02:00 ! # 1.2.2.4 2007-06-12 15:01:13 st2, st5, st7 soft ! # 1.2.2.5 2007-06-12 15:02:23 sb5, sb6 ! # ! # first-dir/f2,v revisions: ! # 1.1 2007-06-12 14:56:15 ! # 1.2 2007-06-12 14:57:34 ! # 1.3 2007-06-12 14:57:46 ! # 1.3.2 branch b1 ! # 1.4 2007-06-12 14:57:58 t2 hard, st3, sb10, sb2, sb3 ! # 1.3.2.1 2007-06-12 14:59:47 ! # 1.3.2.2 2007-06-12 15:00:12 ! # 1.3.2.2.2 branch sb4 ! # 1.3.2.2.4 branch sb5 ! # 1.3.2.3 2007-06-12 15:01:14 st2, st5, st7, sb5 soft, sb6 ! # 1.3.2.4 2007-06-12 15:02:23 ! ! ! dotest soft-tags-1-c "${testcvs} ci -m stags stags" \ ! "$CVSROOT_DIRNAME/CVSROOT/stags,v <-- stags ! new revision: 1\.2; previous revision: 1\.1 ! ${SPROG} commit: Rebuilding administrative file database" ! ! cd ../first-dir ! ! # test 1: branch+date based, all included ! dotest soft-tags-1-e "${testcvs} up -r st2" \ ! "${SPROG} update: Updating \. ! U f1 ! U f2 ! ${SPROG} update: Updating d1 ! U d1/f1" ! dotest soft-tags-1-f "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.2\.2\.4 ! Repository revision: 1\.2\.2\.4 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st2 (revision: 1\.2\.2\.4) ! Sticky Date: (none) ! Sticky Options: (none) ! ! =================================================================== ! File: f2 Status: Up-to-date ! ! Working revision: 1\.3\.2\.3 ! Repository revision: 1\.3\.2\.3 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: st2 (revision: 1\.3\.2\.3) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 2: branch+date based, some are out ! dotest soft-tags-2-a "${testcvs} up -r st1" \ ! "${SPROG} update: Updating \. ! U f1 ! ${SPROG} update: .f2. is no longer in the repository ! ${SPROG} update: Updating d1 ! U d1/f1" ! ! dotest soft-tags-2-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.2\.2\.2 ! Repository revision: 1\.2\.2\.2 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st1 (revision: 1\.2\.2\.2) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 3: tag based, all included ! dotest soft-tags-3-a "${testcvs} up -r st3" \ ! "${SPROG} update: Updating \. ! U f1 ! U f2 ! ${SPROG} update: Updating d1 ! U d1/f1" ! dotest soft-tags-3-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3 ! Repository revision: 1\.3 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st3 (revision: 1\.3) ! Sticky Date: (none) ! Sticky Options: (none) ! ! =================================================================== ! File: f2 Status: Up-to-date ! ! Working revision: 1\.4 ! Repository revision: 1\.4 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: st3 (revision: 1\.4) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 4: tag based, some are out ! dotest soft-tags-4-a "${testcvs} up -r st4" \ ! "${SPROG} update: Updating \. ! U f1 ! ${SPROG} update: .f2. is no longer in the repository ! ${SPROG} update: Updating d1 ! U d1/f1" ! dotest soft-tags-4-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.1 ! Repository revision: 1\.1 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st4 (revision: 1\.1) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 5: tag based, double aliasing ! dotest soft-tags-5-a "${testcvs} up -r st5" \ ! "${SPROG} update: Updating \. ! U f1 ! U f2 ! ${SPROG} update: Updating d1 ! U d1/f1" ! dotest soft-tags-5-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.2\.2\.4 ! Repository revision: 1\.2\.2\.4 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st5 (revision: 1\.2\.2\.4) ! Sticky Date: (none) ! Sticky Options: (none) ! ! =================================================================== ! File: f2 Status: Up-to-date ! ! Working revision: 1\.3\.2\.3 ! Repository revision: 1\.3\.2\.3 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: st5 (revision: 1\.3\.2\.3) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 6: aliasing to non-existent tag ! dotest soft-tags-6 "${testcvs} up -r st6" \ ! "${SPROG} update: Updating \. ! ${SPROG} update: .f1. is no longer in the repository ! ${SPROG} update: .f2. is no longer in the repository ! ${SPROG} update: Updating d1 ! ${SPROG} update: .d1/f1. is no longer in the repository" ! ! # test 7: mixed mode with hard-tag on some file ! dotest soft-tags-7-a "${testcvs} up -r 1.3 f1" ".*" ! dotest soft-tags-7-b "${testcvs} stat f1" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3 ! Repository revision: 1\.3 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: 1\.3 ! Sticky Date: (none) ! Sticky Options: (none)" ! dotest soft-tags-7-c "${testcvs} tag -F st7 f1" \ ! "T f1" ! dotest soft-tags-7-d "${testcvs} up -r st7" ".*" ! dotest soft-tags-7-e "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3 ! Repository revision: 1\.3 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st7 (revision: 1\.3) ! Sticky Date: (none) ! Sticky Options: (none) ! ! =================================================================== ! File: f2 Status: Up-to-date ! ! Working revision: 1\.3\.2\.3 ! Repository revision: 1\.3\.2\.3 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: st7 (revision: 1\.3\.2\.3) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 8: checkout with soft-tag ! cd ../.. ! mkdir 2; cd 2 ! dotest soft-tags-8-a "$testcvs -q co -r st1 first-dir" \ ! "U first-dir/f1 ! U first-dir/d1/f1" ! cd first-dir ! dotest soft-tags-8-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.2\.2\.2 ! Repository revision: 1\.2\.2\.2 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st1 (revision: 1\.2\.2\.2) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! cd ../.. ! rm -rf 2 ! cd 1/first-dir ! ! # test 9: branch+date with branch=trunk, some ! dotest soft-tags-9-a "${testcvs} up -r st9" \ ! "${SPROG} update: Updating \. ! U f1 ! ${SPROG} update: .f2. is no longer in the repository ! ${SPROG} update: Updating d1 ! U d1/f1" ! dotest soft-tags-9-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.2 ! Repository revision: 1\.2 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st9 (revision: 1\.2) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 10: branch+date with branch=trunk, all ! dotest soft-tags-10-a "${testcvs} up -r st10" \ ! "${SPROG} update: Updating \. ! U f1 ! U f2 ! ${SPROG} update: Updating d1 ! U d1/f1" ! dotest soft-tags-10-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3 ! Repository revision: 1\.3 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: st10 (revision: 1\.3) ! Sticky Date: (none) ! Sticky Options: (none) ! ! =================================================================== ! File: f2 Status: Up-to-date ! ! Working revision: 1\.4 ! Repository revision: 1\.4 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: st10 (revision: 1\.4) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 11: hard-tagging a soft branch: ! # - not allowed without -F ! # - allowed with -F if not hard-tagged on file ! # - not allowed at all when hard-tagged on file ! dotest soft-tags-11-a "${testcvs} up -r sb1 f1" ".*" ! dotest soft-tags-11-b "${testcvs} stat f1" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.1 ! Repository revision: 1\.1 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb1 (revision: 1\.1) ! Sticky Date: (none) ! Sticky Options: (none)" ! dotest soft-tags-11-c "${testcvs} up -r 1.2 f1" ".*" ! dotest soft-tags-11-d "${testcvs} tag -b sb1 f1" \ ! "${SPROG} tag: Soft-branch sb1 can only be hard-tagged using '-F' ! W f1 : sb1 already exists on branch 1\.1 : NOT MOVING tag to branch 1\.2\.0\.4" ! dotest soft-tags-11-e "${testcvs} tag -F -b sb1 f1" \ ! "T f1" ! dotest soft-tags-11-f "${testcvs} up -r 1.3 f1" ".*" ! dotest soft-tags-11-g "${testcvs} tag -F -b sb1 f1" \ ! "${SPROG} tag: f1: Not moving branch tag .sb1. from 1\.2 to 1\.3\.0\.2\." ! ! # test 12: commit on soft tag should fail ! dotest soft-tags-12-a "${testcvs} up -r st10" ".*" ! echo "st10 change 1" >> f1 ! dotest_fail soft-tags-12-b "${testcvs} ci -m \"st10 commit\" f1" \ ! "${SPROG} commit: sticky tag .st10. for file .f1. is not a branch ! ${SPROG} \[commit aborted\]: correct above errors first!" ! ! # test 13: soft branch on trunk+date, all. ! # no revisions yet on branch ! rm f1 ! dotest soft-tags-13-a "${testcvs} up -r sb2" ".*" ! dotest soft-tags-13-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3 ! Repository revision: 1\.3 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb2 (revision: 1\.3) ! Sticky Date: (none) ! Sticky Options: (none) ! ! =================================================================== ! File: f2 Status: Up-to-date ! ! Working revision: 1\.4 ! Repository revision: 1\.4 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb2 (revision: 1\.4) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 14: soft-branch sb3 (b+d) on soft-branch sb2 (b+d). ! # no revisions yet on sb2 and sb3 branches ! dotest soft-tags-14-a "${testcvs} up -r sb3" ".*" ! dotest soft-tags-14-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3 ! Repository revision: 1\.3 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb3 (revision: 1\.3) ! Sticky Date: (none) ! Sticky Options: (none) ! ! =================================================================== ! File: f2 Status: Up-to-date ! ! Working revision: 1\.4 ! Repository revision: 1\.4 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb3 (revision: 1\.4) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 15: commit on soft-branch sb2 with no revisions on branch ! dotest soft-tags-15-a "${testcvs} up -r sb2 f1" "" ! echo "sb2 change 1" >> f1 ! dotest soft-tags-15-b "${testcvs} ci -m \"sb2 change 1\" f1" \ ! "$CVSROOT_DIRNAME/first-dir/f1,v <-- f1 ! new revision: 1\.3\.2\.1; previous revision: 1\.3" ! dotest soft-tags-15-c "${testcvs} stat f1" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3\.2\.1 ! Repository revision: 1\.3\.2\.1 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb2 (branch: 1\.3\.2) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 16: commit on soft-branch sb2 with revisions on branch ! # (which means sb2 is now a hard-branch for this specific file) ! echo "sb2 change 2" >> f1 ! dotest soft-tags-16-a "${testcvs} ci -m \"sb2 change 2\" f1" \ ! "$CVSROOT_DIRNAME/first-dir/f1,v <-- f1 ! new revision: 1\.3\.2\.2; previous revision: 1\.3\.2\.1" ! dotest soft-tags-16-b "${testcvs} stat f1" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3\.2\.2 ! Repository revision: 1\.3\.2\.2 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb2 (branch: 1\.3\.2) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 17: commit on soft-branch sb3 with no revisions on branch ! dotest soft-tags-17-a "${testcvs} up -r sb3 f1" ".*" ! echo "sb3 change 1" >> f1 ! dotest soft-tags-17-b "${testcvs} ci -m \"sb3 change 1\" f1" \ ! "$CVSROOT_DIRNAME/first-dir/f1,v <-- f1 ! new revision: 1\.3\.4\.1; previous revision: 1\.3" ! dotest soft-tags-17-c "${testcvs} stat f1" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3\.4\.1 ! Repository revision: 1\.3\.4\.1 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb3 (branch: 1\.3\.4) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 18: commit on soft-branch sb3 with revisions on branch ! echo "sb3 change 2" >> f1 ! dotest soft-tags-18-a "${testcvs} ci -m \"sb3 change 2\" f1" \ ! "$CVSROOT_DIRNAME/first-dir/f1,v <-- f1 ! new revision: 1\.3\.4\.2; previous revision: 1\.3\.4\.1" ! dotest soft-tags-18-b "${testcvs} stat f1" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.3\.4\.2 ! Repository revision: 1\.3\.4\.2 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb3 (branch: 1\.3\.4) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 19: add & commit new file on soft-branch ! dotest soft-tags-19-a "${testcvs} up -r sb2" ".*" ! echo "sb2 change 1" >> f3 ! dotest soft-tags-19-b "${testcvs} add f3" \ ! "${SPROG} add: scheduling file .f3. for addition on branch .sb2. ! ${SPROG} add: use .${SPROG} commit. to add this file permanently" ! dotest soft-tags-19-c "${testcvs} ci -m \"sb3 change 2\" f3" \ ! "$CVSROOT_DIRNAME/first-dir/Attic/f3,v <-- f3 ! new revision: 1\.1\.2\.1; previous revision: 1\.1" ! dotest soft-tags-19-d "${testcvs} stat f3" \ ! "=================================================================== ! File: f3 Status: Up-to-date ! ! Working revision: 1\.1\.2\.1 ! Repository revision: 1\.1\.2\.1 $CVSROOT_DIRNAME/first-dir/Attic/f3,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb2 (branch: 1\.1\.2) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 20: test soft-branch sb4 commit on a hard-branch b1: f1 and f2 ! dotest soft-tags-20-a "${testcvs} up -r sb4" ".*" ! echo "sb4 change 1" >> f1 ! echo "sb4 change 1" >> f2 ! dotest soft-tags-20-b "${testcvs} ci -m \"sb4 change 1\"" \ ! "${SPROG} commit: Examining \. ! ${SPROG} commit: Examining d1 ! $CVSROOT_DIRNAME/first-dir/f1,v <-- f1 ! new revision: 1\.2\.2\.3\.2\.2; previous revision: 1\.2\.2\.3\.2\.1 ! $CVSROOT_DIRNAME/first-dir/f2,v <-- f2 ! new revision: 1\.3\.2\.2\.2\.1; previous revision: 1\.3\.2\.2" ! dotest soft-tags-20-c "${testcvs} stat f1 f2" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.2\.2\.3\.2\.2 ! Repository revision: 1\.2\.2\.3\.2\.2 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb4 (branch: 1\.2\.2\.3\.2) ! Sticky Date: (none) ! Sticky Options: (none) ! ! =================================================================== ! File: f2 Status: Up-to-date ! ! Working revision: 1\.3\.2\.2\.2\.1 ! Repository revision: 1\.3\.2\.2\.2\.1 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb4 (branch: 1\.3\.2\.2\.2) ! Sticky Date: (none) ! Sticky Options: (none)" ! ! # test 21: test hard-branch sb5 overrides soft-branch sb5: ! # f2 update brings 1.3.2.2.4 not 1.3.2.3 ! dotest soft-tags-21-a "${testcvs} up -r sb5" ".*" ! dotest soft-tags-21-b "${testcvs} stat f1 f2" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! ! Working revision: 1\.2\.2\.5 ! Repository revision: 1\.2\.2\.5 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb5 (revision: 1\.2\.2\.5) ! Sticky Date: (none) ! Sticky Options: (none) ! =================================================================== ! File: f2 Status: Up-to-date ! Working revision: 1\.3\.2\.2 ! Repository revision: 1\.3\.2\.2 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb5 (branch: 1\.3\.2\.2\.4) ! Sticky Date: (none) ! Sticky Options: (none)" ! # test 22: remove on branch with no revisions ! dotest soft-tags-22-a "${testcvs} up -r sb6" ".*" ! dotest soft-tags-22-b "${testcvs} stat f1" \ ! "=================================================================== ! File: f1 Status: Up-to-date ! Working revision: 1\.2\.2\.5 ! Repository revision: 1\.2\.2\.5 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb6 (revision: 1\.2\.2\.5) ! Sticky Date: (none) ! Sticky Options: (none)" ! rm f1 ! dotest soft-tags-22-c "${testcvs} rm f1" ".*" ! dotest soft-tags-22-d "${testcvs} ci -m \"remove f1 on branch sb6\"" \ ! "${SPROG} commit: Examining \. ! ${SPROG} commit: Examining d1 ! $CVSROOT_DIRNAME/first-dir/f1,v <-- f1 ! new revision: delete; previous revision: 1\.2\.2\.5" ! ! # test 23: cvs up on hard branch ! dotest soft-tags-23-a "${testcvs} up -r b1" ".*" ! dotest soft-tags-23-b "${testcvs} stat" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! Working revision: 1\.2\.2\.5 ! Repository revision: 1\.2\.2\.5 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: b1 (branch: 1\.2\.2) ! Sticky Date: (none) ! Sticky Options: (none) ! =================================================================== ! File: f2 Status: Up-to-date ! Working revision: 1\.3\.2\.4 ! Repository revision: 1\.3\.2\.4 $CVSROOT_DIRNAME/first-dir/f2,v ! Commit Identifier: ${commitid} ! Sticky Tag: b1 (branch: 1\.3\.2) ! Sticky Date: (none) ! Sticky Options: (none) + ${SPROG} status: Examining d1 + =================================================================== + File: f1 Status: Up-to-date + Working revision: 1\.2\.2\.5 + Repository revision: 1\.2\.2\.5 $CVSROOT_DIRNAME/first-dir/d1/f1,v + Commit Identifier: ${commitid} + Sticky Tag: b1 (branch: 1\.2\.2) + Sticky Date: (none) + Sticky Options: (none)" ! # test 24: cvs co on hard branch ! cd ../.. ! mkdir 2; cd 2 ! dotest soft-tags-24-a "$testcvs -q co -r b1 first-dir" ".*" cd first-dir ! dotest soft-tags-24-b "${testcvs} stat -l" \ ! "${SPROG} status: Examining \. ! =================================================================== ! File: f1 Status: Up-to-date ! Working revision: 1\.2\.2\.5 ! Repository revision: 1\.2\.2\.5 $CVSROOT_DIRNAME/first-dir/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: b1 (branch: 1\.2\.2) ! Sticky Date: (none) ! Sticky Options: (none) + =================================================================== + File: f2 Status: Up-to-date + Working revision: 1\.3\.2\.4 + Repository revision: 1\.3\.2\.4 $CVSROOT_DIRNAME/first-dir/f2,v + Commit Identifier: ${commitid} + Sticky Tag: b1 (branch: 1\.3\.2) + Sticky Date: (none) + Sticky Options: (none)" ! cd ../.. ! rm -rf 2 ! cd 1/first-dir ! ! # test 25: update on soft-branch with repository set to subdir ! dotest soft-tags-25-a "${testcvs} up -dP -A" \ ! "${SPROG} update: Updating \. ! U f1 ! U f2 ! ${SPROG} update: Updating d1 ! U d1/f1" ! dotest soft-tags-25-b "${testcvs} up -r sb7" \ ! "${SPROG} update: Updating \. ! ${SPROG} update: .f1. is no longer in the repository ! ${SPROG} update: .f2. is no longer in the repository ! ${SPROG} update: Updating d1 ! U d1/f1" ! dotest soft-tags-25-c "${testcvs} stat" \ ! "${SPROG} status: Examining \. ! ${SPROG} status: Examining d1 ! =================================================================== ! File: f1 Status: Up-to-date ! Working revision: 1\.2\.2\.2 ! Repository revision: 1\.2\.2\.2 $CVSROOT_DIRNAME/first-dir/d1/f1,v ! Commit Identifier: ${commitid} ! Sticky Tag: sb7 (revision: 1\.2\.2\.2) ! Sticky Date: (none) ! Sticky Options: (none)" ! # test 26: test soft-branch update with -r -D