cb6306bf42be62003edb04945ab26f26c28afaa6
max
  Tue May 9 01:12:38 2023 -0700
changing copy to duplicate of cloned track, after long discussion of what a duplicate is and when to starting counting, refs #30911

diff --git src/hg/lib/dupTrack.c src/hg/lib/dupTrack.c
index 4f21625..c969062 100644
--- src/hg/lib/dupTrack.c
+++ src/hg/lib/dupTrack.c
@@ -34,80 +34,80 @@
     }
 return name;
 }
 
 static void makeDupName(char *sourceName, int n, char *buf, int bufSize)
 /* Create name for dupe */
 {
 char *source = dupTrackSkipToSourceName(sourceName);
 safef(buf, bufSize, "%s%d_%s", DUP_TRACK_PREFIX, n, source);
 }
 
 static void findUniqDupName(char *sourceName, struct hash *dupHash, char nameBuf[], int nameBufSize)
 /* Make up a name of format dup_N_sourceTrack where N is a small unique number */
 {
 int i;
-for (i=1; ;++i)
+for (i=0; ;++i)
     {
     makeDupName(sourceName, i, nameBuf, nameBufSize);
     if (!hashLookup(dupHash, nameBuf))
 	return;
     }
 }
 
 char *dupTrackInCartAndTrash(char *sourceTrack, struct cart *cart, struct trackDb *sourceTdb)
 /* Update cart vars to reflect existance of duplicate of sourceTrack.
  * Also write out or append to dupe track trash file */
 {
 char *dupFileName = cartUsualString(cart, DUP_TRACKS_VAR, NULL);
 FILE *f = NULL;	    // This will be our output
 
 /* We keep duplicate's name here. */
 int bufSize = strlen(sourceTrack) + 32;
 char dupeTrackName[bufSize];
-makeDupName(sourceTrack, 1, dupeTrackName, sizeof(dupeTrackName));
+makeDupName(sourceTrack, 0, dupeTrackName, sizeof(dupeTrackName));
 
 if (dupFileName != NULL && fileExists(dupFileName))   // Try and read in from old file
     {
     /* If there are already duplicates and trash cleaner hasn't nuked file read it in
      * and make sre we come up with a unique name before we append to existing file */
     struct hash *dupHash = raReadAll(dupFileName, "track");
     findUniqDupName(sourceTrack, dupHash, dupeTrackName, sizeof(dupeTrackName));
     f = mustOpen(dupFileName, "a");	// Append to old file but use new name
     fputc('\n', f);
     }
 else
     {
     /* Otherwise we need to make up a new temp file and recored it in the cart */
     struct tempName dupTn;
     trashDirDateFile(&dupTn, "dup", "dup", ".ra");
     f = mustOpen(dupTn.forCgi, "w");
     cartSetString(cart, DUP_TRACKS_VAR, dupTn.forCgi);
     }
 /* Write out new stanza */
 fprintf(f, "track %s\n", dupeTrackName);
 fprintf(f, "source %s\n", dupTrackSkipToSourceName(sourceTrack));
 int dupNo = atoi(dupeTrackName + strlen(DUP_TRACK_PREFIX)) + 1;
 if (sourceTdb != NULL)
     {
     fprintf(f, "shortLabel %s #%d\n", sourceTdb->shortLabel, dupNo);
-    fprintf(f, "longLabel %s copy #%d\n", sourceTdb->longLabel, dupNo);
+    fprintf(f, "longLabel %s #%d (duplicate)\n", sourceTdb->longLabel, dupNo);
     }
 else
     {
     fprintf(f, "%s #%d\n", sourceTrack, dupNo);
-    fprintf(f, "longLabel %s copy #%d\n", sourceTrack, dupNo);
+    fprintf(f, "longLabel %s #%d (duplicate)\n", sourceTrack, dupNo);
     }
 carefulClose(&f);
 
 cartCloneVarsWithPrefix(cart, sourceTrack, dupeTrackName);
 return cloneString(dupeTrackName);
 }
 
 static void cartRemoveConfigVarsForTrack(struct cart *cart, char *track)
 /* Remove track, track.* and track_*.  Perhaps this is more cautious than
  * track*? */
 {
 cartRemove(cart, track);
 int nameSize = strlen(track);
 char namePlusBuf[nameSize+2];
 strcpy(namePlusBuf, track);