From: VGris AT aironet DOT com ("Griswold, Victor") Subject: CVS 1.9: RCS_merge Timestamp Anomaly 5 Mar 1997 18:27:00 -0800 Approved: cygnus DOT gnu-win32 AT cygnus DOT com Distribution: cygnus Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Original-To: "'Cygnus:GNU-WIN32'" , "'bug-cvs AT prep DOT ai DOT mit DOT edu'" X-Mailer: Microsoft Exchange Server Internet Mail Connector Version 4.0.994.63 Original-Sender: owner-gnu-win32 AT cygnus DOT com Gentlemen: Enclosed is a patch to the CVS 1.9 distribution which corrects a subtle problem with "cvs checkout -j". The problem is that, on fast workstations, a checkout followed by a merge can take place within the time quantum of the filesystem (1 second on Unix, 2 seconds on DOS/Windows FAT). The result is that, on a subsequent commit, cvs compares the checkout timestamp with the file timestamp (which are equal) and incorrectly believes that no merge had been done on the file. This patch also stabilizes running sanity.sh somewhat when executing on fast workstations, particularly ones utilizing the DOS/Windows FAT filesystem. The mechanism utilized by the patch is simply to check the file timestamp before the merge, then after the merge. If they remain the same, RCS_merge waits one second, touches the merged file, and checks again. This message is cross-posted to the cygnus gnu-win32 mailing list because of recent interest in CVS in that mailing list. Future bug-fixes will be posted only to the bug-cvs mailing list. For those interested in that mailing list, subscribe by sending "subscribe bug-cvs" in a mail message to bug-cvs-request AT prep DOT ai DOT mit DOT edu. Victor J. Griswold, D.Sc. Aironet Wireless Communications, Inc. voice: 330-664-7987 fax: 330-664-7301 email: (MS-Mail) vgris AT aironet DOT com (MIME) Victor DOT Griswold AT pobox DOT com Index: CVS_src/ChangeLog diff -c CVS_src/ChangeLog:1.1.1.1 CVS_src/ChangeLog:1.1.1.1.2.1 *** CVS_src/ChangeLog:1.1.1.1 Wed Dec 31 19:00:49 1969 --- CVS_src/ChangeLog Wed Dec 31 18:56:32 1969 *************** *** 1,3 **** --- 1,10 ---- + Wed Mar 5 1997 Victor Griswold + * Fixed RCS_merge timestamp anomaly in which a merged file could + have the same timestamp as the original file. This can occur + on a fast workstation when executing "cvs checkout -j". The + result is that a later "cvs commit" fails to detect the merged + files because the timestamps are the same. + Tue Oct 1 14:32:44 1996 Jim Kingdon * NEWS, README: Revert changes regarding -D, -g, and A4. They Index: CVS_src/src/cvs.h diff -c CVS_src/src/cvs.h:1.1.1.1.2.1 CVS_src/src/cvs.h:1.1.1.1.2.2 *** CVS_src/src/cvs.h:1.1.1.1.2.1 Wed Dec 31 18:58:46 1969 --- CVS_src/src/cvs.h Wed Dec 31 18:56:45 1969 *************** *** 334,340 **** typedef enum direnter_type Dtype; #endif ! extern char *program_name, *program_path, *command_name; extern char *Rcsbin, *Tmpdir, *Editor; extern int cvsadmin_root; extern char *CurDir; --- 334,341 ---- typedef enum direnter_type Dtype; #endif ! extern const char *program_name; ! extern char *program_path, *command_name; extern char *Rcsbin, *Tmpdir, *Editor; extern int cvsadmin_root; extern char *CurDir; *************** *** 404,410 **** char *Short_Repository PROTO((char *repository)); char *gca PROTO((char *rev1, char *rev2)); char *getcaller PROTO((void)); ! char *time_stamp PROTO((char *file)); char *xmalloc PROTO((size_t bytes)); void *xrealloc PROTO((void *ptr, size_t bytes)); char *xstrdup PROTO((const char *str)); --- 405,411 ---- char *Short_Repository PROTO((char *repository)); char *gca PROTO((char *rev1, char *rev2)); char *getcaller PROTO((void)); ! char *time_stamp PROTO((const char *file)); char *xmalloc PROTO((size_t bytes)); void *xrealloc PROTO((void *ptr, size_t bytes)); char *xstrdup PROTO((const char *str)); *************** *** 422,428 **** int iswritable PROTO((const char *file)); int isaccessible PROTO((const char *file, const int mode)); int isabsolute PROTO((const char *filename)); ! char *last_component PROTO((char *path)); char *get_homedir PROTO ((void)); char *cvs_temp_name PROTO ((void)); --- 423,429 ---- int iswritable PROTO((const char *file)); int isaccessible PROTO((const char *file, const int mode)); int isabsolute PROTO((const char *filename)); ! const char *last_component PROTO((const char *path)); char *get_homedir PROTO ((void)); char *cvs_temp_name PROTO ((void)); Index: CVS_src/src/filesubr.c diff -c CVS_src/src/filesubr.c:1.1.1.1.2.2 CVS_src/src/filesubr.c:1.1.1.1.2.4 *** CVS_src/src/filesubr.c:1.1.1.1.2.2 Wed Dec 31 18:57:23 1969 --- CVS_src/src/filesubr.c Wed Dec 31 18:56:47 1969 *************** *** 834,844 **** /* Return a pointer into PATH's last component. */ ! char * ! last_component (char *path) { ! char *scan; ! char *last = 0; for (scan = path; *scan; scan++) if (ISDIRSEP (*scan)) --- 838,848 ---- /* Return a pointer into PATH's last component. */ ! const char * ! last_component (const char *path) { ! const char *scan; ! const char *last = 0; for (scan = path; *scan; scan++) if (ISDIRSEP (*scan)) Index: CVS_src/src/main.c diff -c CVS_src/src/main.c:1.1.1.1.2.1 CVS_src/src/main.c:1.1.1.1.2.2 *** CVS_src/src/main.c:1.1.1.1.2.1 Wed Dec 31 18:57:30 1969 --- CVS_src/src/main.c Wed Dec 31 18:56:48 1969 *************** *** 20,26 **** extern int gethostname (); #endif ! char *program_name; char *program_path; char *command_name; --- 20,26 ---- extern int gethostname (); #endif ! const char *program_name; char *program_path; char *command_name; Index: CVS_src/src/rcs.h diff -c CVS_src/src/rcs.h:1.1.1.1 CVS_src/src/rcs.h:1.1.1.1.2.1 *** CVS_src/src/rcs.h:1.1.1.1 Wed Dec 31 19:00:58 1969 --- CVS_src/src/rcs.h Wed Dec 31 18:56:49 1969 *************** *** 17,22 **** --- 17,23 ---- #define RCS_RCSMERGE "rcsmerge" #define RCS_MERGE_PAT "^>>>>>>> " /* runs "grep" with this pattern */ #define RCSEXT ",v" + #define RCSEXT_LEN (2) #define RCSPAT "*,v" #define RCSHEAD "head" #define RCSBRANCH "branch" Index: CVS_src/src/rcscmds.c diff -c CVS_src/src/rcscmds.c:1.1.1.1 CVS_src/src/rcscmds.c:1.1.1.1.2.1 *** CVS_src/src/rcscmds.c:1.1.1.1 Wed Dec 31 19:01:02 1969 --- CVS_src/src/rcscmds.c Wed Dec 31 18:56:50 1969 *************** *** 143,151 **** --- 143,161 ---- const char *rev2; { int status; + int delay_status; + const char *archiveName = last_component(path); + char *userFile; + char *timeBefore; + char *timeAfter; /* XXX - Do merge by hand instead of using rcsmerge, due to -k handling */ + userFile = xstrdup(archiveName); + userFile[strlen(archiveName) - RCSEXT_LEN] = '\0'; + + timeBefore = time_stamp(userFile); + run_setup ("%s%s -x,v/ %s -r%s -r%s %s", Rcsbin, RCS_RCSMERGE, options, rev1, rev2, path); status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); *************** *** 160,165 **** --- 170,201 ---- } #endif + + timeAfter = time_stamp(userFile); + while (timeAfter && strcmp(timeBefore, timeAfter) == 0) { + free(timeAfter); + + if (trace) { + fprintf(stderr, "-> RCS_merge: timestamp of file %s is %s before and after merge.\n", + userFile, timeBefore); + } + + /* Force the time stamp on the merged file to be different */ + /* if the file was just checked out. This avoids confusing */ + /* Classify_File. */ + /**/ + sleep(1); + run_setup ("touch %s", userFile); + delay_status = run_exec (RUN_TTY, DEVNULL, RUN_TTY, RUN_NORMAL); + + timeAfter = time_stamp(userFile); + } + + free(userFile); + if (timeBefore) + free(timeBefore); + if (timeAfter) + free(timeAfter); return status; } Index: CVS_src/src/recurse.c diff -c CVS_src/src/recurse.c:1.1.1.1.2.1 CVS_src/src/recurse.c:1.1.1.1.2.2 *** CVS_src/src/recurse.c:1.1.1.1.2.1 Wed Dec 31 18:59:05 1969 --- CVS_src/src/recurse.c Wed Dec 31 18:56:51 1969 *************** *** 189,195 **** /* Now break out argv[i] into directory part (DIR) and file part (COMP). DIR and COMP will each point to a newly malloc'd string. */ dir = xstrdup (argv[i]); ! comp = last_component (dir); if (comp == dir) { /* no dir component. What we have is an implied "./" */ --- 189,195 ---- /* Now break out argv[i] into directory part (DIR) and file part (COMP). DIR and COMP will each point to a newly malloc'd string. */ dir = xstrdup (argv[i]); ! comp = (char*)last_component (dir); if (comp == dir) { /* no dir component. What we have is an implied "./" */ *************** *** 670,676 **** } /* put back update_dir */ ! cp = last_component (update_dir); if (cp > update_dir) cp[-1] = '\0'; else --- 670,676 ---- } /* put back update_dir */ ! cp = (char*)last_component (update_dir); if (cp > update_dir) cp[-1] = '\0'; else Index: CVS_src/src/vers_ts.c diff -c CVS_src/src/vers_ts.c:1.1.1.1 CVS_src/src/vers_ts.c:1.1.1.1.2.1 *** CVS_src/src/vers_ts.c:1.1.1.1 Wed Dec 31 19:01:03 1969 --- CVS_src/src/vers_ts.c Wed Dec 31 18:56:55 1969 *************** *** 274,280 **** */ char * time_stamp (file) ! char *file; { struct stat sb; char *cp; --- 274,280 ---- */ char * time_stamp (file) ! const char *file; { struct stat sb; char *cp; - For help on using this list, send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".