569360530e4b6780aa4a75cecb37592741e42ade
larrym
  Mon Mar 14 14:32:10 2011 -0700
use CGI version based softlinks for js and css files in production sites (see redmine 3170
diff --git src/hg/lib/web.c src/hg/lib/web.c
index 02bdafe..08ed3b7 100644
--- src/hg/lib/web.c
+++ src/hg/lib/web.c
@@ -1318,60 +1318,64 @@
 char *docRoot = hDocumentRoot();
 if(docRoot != NULL) // tolerate missing docRoot (i.e. when running from command line)
     fullDirName = dyStringCreate("%s/%s", docRoot, dirName);
 else
     fullDirName = dyStringCreate("%s", dirName);
 if(!fileExists(dyStringContents(fullDirName)))
     errAbort("webTimeStampedLinkToResource: dir: %s doesn't exist.\n", dyStringContents(fullDirName));
 
 // build and verify real path to file
 struct dyString *realFileName = dyStringCreate("%s/%s", dyStringContents(fullDirName), fileName);
 if(!fileExists(dyStringContents(realFileName)))
     errAbort("webTimeStampedLinkToResource: file: %s doesn't exist.\n", dyStringContents(realFileName));
 
 // build and verify link path including timestamp in the form of dir/baseName-timeStamp.ext
 long mtime = fileModTime(dyStringContents(realFileName));   // We add mtime to create a pseudo-version; this forces browsers to reload css/js file when it changes
-struct dyString *linkWithTimestamp = dyStringCreate("%s/%s-%ld%s", dyStringContents(fullDirName), baseName, mtime, extension);
+struct dyString *linkWithTimestamp;
+if(hIsPreviewHost() || hIsPrivateHost())
+    linkWithTimestamp = dyStringCreate("%s/%s-%ld%s", dyStringContents(fullDirName), baseName, mtime, extension);
+else
+    linkWithTimestamp = dyStringCreate("%s/%s-v%s%s", dyStringContents(fullDirName), baseName, CGI_VERSION, extension);
 
 // If link does not exist, then create it !!
 if(!fileExists(dyStringContents(linkWithTimestamp)))
     {
     // The versioned copy should be created by the install process; however, mirrors may fail
     // to preserve mtime's when copying over the javascript/css files, in which case the
     // versioned softlinks won't match the real file; in that case, we try to create
     // the versioned links on the fly (which requires write access to the javascript or style directory!).
 
     // Remove older links
     struct dyString *pattern = dyStringCreate("%s-[0-9]+\\%s", baseName, extension);
     struct slName *file, *files = listDirRegEx(dyStringContents(fullDirName), dyStringContents(pattern), REG_EXTENDED);
     struct dyString *oldLink = dyStringNew(256);
     for (file = files; file != NULL; file = file->next)
         {
         dyStringClear(oldLink);
         dyStringPrintf(oldLink, "%s/%s", dyStringContents(fullDirName), file->name);
         unlink(dyStringContents(oldLink));
         }
     dyStringFree(&oldLink);
     slFreeList(&files);
     dyStringFree(&pattern);
 
     // Create new link
     if(symlink(dyStringContents(realFileName), dyStringContents(linkWithTimestamp)))
         {
         int err = errno;
-        errAbort("webTimeStampedLinkToResource: symlink failed: errno: %d (%s); the directory '%s' must be writeable by user '%s'; alternatively, the installation process must create the versioned files\n",
-                    err, strerror(err), dyStringContents(fullDirName), getUser());
+        errAbort("webTimeStampedLinkToResource: symlink of %s failed: errno: %d (%s); the directory '%s' must be writeable by user '%s'; alternatively, the installation process must create the versioned files\n",
+                 dyStringContents(linkWithTimestamp), err, strerror(err), dyStringContents(fullDirName), getUser());
         }
     }
 // Free up all that extra memory
 dyStringFree(&realFileName);
 dyStringFree(&fullDirName);
 char *linkFull = dyStringCannibalize(&linkWithTimestamp);
 char *link = linkFull;
 if (docRoot != NULL)
     link = cloneString(linkFull + strlen(docRoot) + 1);
 freeMem(linkFull);
 
 if (wrapInHtml) // wrapped for christmas
     {
     struct dyString *wrapped = dyStringNew(0);
     if (js)