Commits

Greg Ward committed dfc398e

Track relative path from working copy root to start dir.
- add rel_path to vccontext_t
- rewrite probe_parents() so it figures out and sets rel_path
(also rename it to probe_dirs())

  • Participants
  • Parent commits 0215eb0

Comments (0)

Files changed (3)

 void
 free_context(vccontext_t *context)
 {
+    free(context->rel_path);
     free(context);
 }
 
     const char *name;                   /* name of the VC system */
     options_t *options;
 
+    /* Path from wc root to cwd: eg. if we're in foo/bar/baz, but wc
+     * metadata is in foo/.hg (or whatever), rel_path is "bar/baz".
+     * Only makes sense for VC systems with a single metadata
+     * directory for a whole tree: git, hg, svn >= 1.7, etc.
+     */
+    char *rel_path;
+
     /* context methods */
     int (*probe)(vccontext_t*);
     result_t* (*get_info)(vccontext_t*);
 #include <sys/time.h>
 #include <unistd.h>
 #include <signal.h>
+#include <errno.h>
+#include <limits.h>
 
 #include "common.h"
 #include "cvs.h"
 
 /* walk up the directory tree until the probes work or we hit / */
 vccontext_t*
-probe_parents(vccontext_t** contexts, int num_contexts)
+probe_dirs(vccontext_t** contexts, int num_contexts)
 {
-    vccontext_t *context;
-    struct stat rootdir;
-    struct stat curdir;
+    char *start_dir = malloc(PATH_MAX);
+    if (getcwd(start_dir, PATH_MAX) == NULL) {
+        debug("getcwd() failed: %s", strerror(errno));
+        free(start_dir);
+        return NULL;
+    }
+    char *rel_path = start_dir + strlen(start_dir);
 
-    stat("/", &rootdir);
+    vccontext_t *context = NULL;
     while (1) {
         context = probe_all(contexts, num_contexts);
         if (context != NULL) {
-            debug("found a context");
-            return context;
+            break;
+        }
+        if (rel_path == start_dir + 1) {
+            debug("reached the root: %s not under version control", start_dir);
+            break;
         }
 
-        stat(".", &curdir);
-        int isroot = (rootdir.st_dev == curdir.st_dev &&
-                      rootdir.st_ino == curdir.st_ino);
-        if (isroot || (-1 == chdir(".."))) {
-            return NULL;
+        debug("no context claimed current dir: walking up the tree");
+        if (-1 == chdir("..")) {
+            debug("chdir(\"..\") failed: %s", strerror(errno));
+            break;
         }
-	debug("no context claimed current dir: walking up the tree");
+        do {
+            rel_path--;
+        } while (rel_path > start_dir && rel_path[-1] != '/');
     }
+    if (context != NULL) {
+        debug("found a context: %s (rel_path=%s)", context->name, rel_path);
+        context->rel_path = strdup(rel_path);
+    }
+    free(start_dir);
+    return context;
 }
 
 /* The signal handler just clears the flag and re-enables itself.  */
 
     /* Starting in the current dir, walk up the directory tree until
        someone claims that this is a working copy. */
-    context = probe_parents(contexts, num_contexts);
+    context = probe_dirs(contexts, num_contexts);
 
     /* Nobody claimed it: bail now without printing anything. */
     if (context == NULL) {
 
  done:
     for (int i = 0; i < num_contexts; i++) {
-        free(contexts[i]);
+        free_context(contexts[i]);
     }
     return status;
 }