Code

Make it possible to set up libgit directly (instead of from the environment)
authorPetr Baudis <pasky@suse.cz>
Mon, 3 Jul 2006 20:48:03 +0000 (22:48 +0200)
committerJunio C Hamano <junkio@cox.net>
Sun, 9 Jul 2006 08:20:01 +0000 (01:20 -0700)
This introduces a setup_git() function which is essentialy a (public)
backend for setup_git_env() which lets anyone specify custom sources
for the various paths instead of environment variables. Since the repositories
may get switched on the fly, this also updates code that caches paths to
invalidate them properly; I hope neither of those is a sweet spot.

It is used by Git.xs' xs__call_gate() to set up per-repository data
for libgit's consumption. No code actually takes advantage of it yet
but get_object() will in the next patches.

Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Junio C Hamano <junkio@cox.net>
cache.h
commit.c
environment.c
perl/Git.pm
perl/Git.xs
sha1_file.c
sha1_name.c

diff --git a/cache.h b/cache.h
index 87199396a05fbbbb695379119535eb9eefae2514..962f2fc3467077289df4294b48216050b26e74a7 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -116,6 +116,9 @@ extern struct cache_entry **active_cache;
 extern unsigned int active_nr, active_alloc, active_cache_changed;
 extern struct cache_tree *active_cache_tree;
 
+extern void setup_git(char *new_git_dir, char *new_git_object_dir,
+                      char *new_git_index_file, char *new_git_graft_file);
+
 #define GIT_DIR_ENVIRONMENT "GIT_DIR"
 #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
 #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
index e51ffa1c6cf5948c0e6c6d0b905fc868f4464ccf..17f51c245525172695e6ff6d36990464349558e0 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -163,6 +163,14 @@ int register_commit_graft(struct commit_graft *graft, int ignore_dups)
        return 0;
 }
 
+void free_commit_grafts(void)
+{
+       int pos = commit_graft_nr;
+       while (pos >= 0)
+               free(commit_graft[pos--]);
+       commit_graft_nr = 0;
+}
+
 struct commit_graft *read_graft_line(char *buf, int len)
 {
        /* The format is just "Commit Parent1 Parent2 ...\n" */
@@ -215,11 +223,18 @@ int read_graft_file(const char *graft_file)
 static void prepare_commit_graft(void)
 {
        static int commit_graft_prepared;
-       char *graft_file;
+       static char *last_graft_file;
+       char *graft_file = get_graft_file();
+
+       if (last_graft_file) {
+               if (!strcmp(graft_file, last_graft_file))
+                       return;
+               free_commit_grafts();
+       }
+       if (last_graft_file)
+               free(last_graft_file);
+       last_graft_file = strdup(graft_file);
 
-       if (commit_graft_prepared)
-               return;
-       graft_file = get_graft_file();
        read_graft_file(graft_file);
        commit_graft_prepared = 1;
 }
index 3de8eb3b2a2359a9f8a9f702076292f1e1429df3..6b64d111f584d5e80fa7dc2e1bf0d5ab2a69ba7b 100644 (file)
@@ -21,28 +21,61 @@ char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
 int shared_repository = PERM_UMASK;
 const char *apply_default_whitespace = NULL;
 
+static int dyn_git_object_dir, dyn_git_index_file, dyn_git_graft_file;
 static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
        *git_graft_file;
-static void setup_git_env(void)
+
+void setup_git(char *new_git_dir, char *new_git_object_dir,
+               char *new_git_index_file, char *new_git_graft_file)
 {
-       git_dir = getenv(GIT_DIR_ENVIRONMENT);
+       git_dir = new_git_dir;
        if (!git_dir)
                git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
-       git_object_dir = getenv(DB_ENVIRONMENT);
+
+       if (dyn_git_object_dir)
+               free(git_object_dir);
+       git_object_dir = new_git_object_dir;
        if (!git_object_dir) {
                git_object_dir = xmalloc(strlen(git_dir) + 9);
                sprintf(git_object_dir, "%s/objects", git_dir);
+               dyn_git_object_dir = 1;
+       } else {
+               dyn_git_object_dir = 0;
        }
+
+       if (git_refs_dir)
+               free(git_refs_dir);
        git_refs_dir = xmalloc(strlen(git_dir) + 6);
        sprintf(git_refs_dir, "%s/refs", git_dir);
-       git_index_file = getenv(INDEX_ENVIRONMENT);
+
+       if (dyn_git_index_file)
+               free(git_index_file);
+       git_index_file = new_git_index_file;
        if (!git_index_file) {
                git_index_file = xmalloc(strlen(git_dir) + 7);
                sprintf(git_index_file, "%s/index", git_dir);
+               dyn_git_index_file = 1;
+       } else {
+               dyn_git_index_file = 0;
        }
-       git_graft_file = getenv(GRAFT_ENVIRONMENT);
-       if (!git_graft_file)
+
+       if (dyn_git_graft_file)
+               free(git_graft_file);
+       git_graft_file = new_git_graft_file;
+       if (!git_graft_file) {
                git_graft_file = strdup(git_path("info/grafts"));
+               dyn_git_graft_file = 1;
+       } else {
+               dyn_git_graft_file = 0;
+       }
+}
+
+static void setup_git_env(void)
+{
+       setup_git(getenv(GIT_DIR_ENVIRONMENT),
+                 getenv(DB_ENVIRONMENT),
+                 getenv(INDEX_ENVIRONMENT),
+                 getenv(GRAFT_ENVIRONMENT));
 }
 
 char *get_git_dir(void)
index 9ce9fcdd3ec95f08a7bf6c00bdd6da2931c01cde..9da15e9c8c208ffd6a51b524edc828c85dce5355 100644 (file)
@@ -98,6 +98,8 @@ XSLoader::load('Git', $VERSION);
 
 }
 
+my $instance_id = 0;
+
 
 =head1 CONSTRUCTORS
 
@@ -215,7 +217,7 @@ sub repository {
                delete $opts{Directory};
        }
 
-       $self = { opts => \%opts };
+       $self = { opts => \%opts, id => $instance_id++ };
        bless $self, $class;
 }
 
@@ -833,11 +835,10 @@ sub _call_gate {
        if (defined $self) {
                # XXX: We ignore the WorkingCopy! To properly support
                # that will require heavy changes in libgit.
+               # For now, when we will need to do it we could temporarily
+               # chdir() there and then chdir() back after the call is done.
 
-               # XXX: And we ignore everything else as well. libgit
-               # at least needs to be extended to let us specify
-               # the $GIT_DIR instead of looking it up in environment.
-               #xs_call_gate($self->{opts}->{Repository});
+               xs__call_gate($self->{id}, $self->repo_path());
        }
 
        # Having to call throw from the C code is a sure path to insanity.
index 2bbec4365f9c244a7a905df702393bca591d9d67..6ed26a29b89ab1959ef2e62917fb72c137bab39f 100644 (file)
@@ -52,7 +52,21 @@ BOOT:
 }
 
 
-# /* TODO: xs_call_gate(). See Git.pm. */
+void
+xs__call_gate(repoid, git_dir)
+       long repoid;
+       char *git_dir;
+CODE:
+{
+       static long last_repoid;
+       if (repoid != last_repoid) {
+               setup_git(git_dir,
+                         getenv(DB_ENVIRONMENT),
+                         getenv(INDEX_ENVIRONMENT),
+                         getenv(GRAFT_ENVIRONMENT));
+               last_repoid = repoid;
+       }
+}
 
 
 char *
index 817963045b81cef36bf3a9c76b7399a70226a181..ab64543d4a948ba9aee461d874dfba9a09a67dd6 100644 (file)
@@ -126,16 +126,22 @@ static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
 char *sha1_file_name(const unsigned char *sha1)
 {
        static char *name, *base;
+       static const char *last_objdir;
+       const char *sha1_file_directory = get_object_directory();
 
-       if (!base) {
-               const char *sha1_file_directory = get_object_directory();
+       if (!last_objdir || strcmp(last_objdir, sha1_file_directory)) {
                int len = strlen(sha1_file_directory);
+               if (base)
+                       free(base);
                base = xmalloc(len + 60);
                memcpy(base, sha1_file_directory, len);
                memset(base+len, 0, 60);
                base[len] = '/';
                base[len+3] = '/';
                name = base + len + 1;
+               if (last_objdir)
+                       free((char *) last_objdir);
+               last_objdir = strdup(sha1_file_directory);
        }
        fill_sha1_path(name, sha1);
        return base;
@@ -145,14 +151,20 @@ char *sha1_pack_name(const unsigned char *sha1)
 {
        static const char hex[] = "0123456789abcdef";
        static char *name, *base, *buf;
+       static const char *last_objdir;
+       const char *sha1_file_directory = get_object_directory();
        int i;
 
-       if (!base) {
-               const char *sha1_file_directory = get_object_directory();
+       if (!last_objdir || strcmp(last_objdir, sha1_file_directory)) {
                int len = strlen(sha1_file_directory);
+               if (base)
+                       free(base);
                base = xmalloc(len + 60);
                sprintf(base, "%s/pack/pack-1234567890123456789012345678901234567890.pack", sha1_file_directory);
                name = base + len + 11;
+               if (last_objdir)
+                       free((char *) last_objdir);
+               last_objdir = strdup(sha1_file_directory);
        }
 
        buf = name;
@@ -170,14 +182,20 @@ char *sha1_pack_index_name(const unsigned char *sha1)
 {
        static const char hex[] = "0123456789abcdef";
        static char *name, *base, *buf;
+       static const char *last_objdir;
+       const char *sha1_file_directory = get_object_directory();
        int i;
 
-       if (!base) {
-               const char *sha1_file_directory = get_object_directory();
+       if (!last_objdir || strcmp(last_objdir, sha1_file_directory)) {
                int len = strlen(sha1_file_directory);
+               if (base)
+                       free(base);
                base = xmalloc(len + 60);
                sprintf(base, "%s/pack/pack-1234567890123456789012345678901234567890.idx", sha1_file_directory);
                name = base + len + 11;
+               if (last_objdir)
+                       free((char *) last_objdir);
+               last_objdir = strdup(sha1_file_directory);
        }
 
        buf = name;
index f2cbafa496231e7a9cdbbea2ab4e7d4c4ed761ab..c698c1b0b00dcb761e93779797795e8ce8cb5313 100644 (file)
@@ -12,15 +12,21 @@ static int find_short_object_filename(int len, const char *name, unsigned char *
        char hex[40];
        int found = 0;
        static struct alternate_object_database *fakeent;
+       static const char *last_objdir;
+       const char *objdir = get_object_directory();
 
-       if (!fakeent) {
-               const char *objdir = get_object_directory();
+       if (!last_objdir || strcmp(last_objdir, objdir)) {
                int objdir_len = strlen(objdir);
                int entlen = objdir_len + 43;
+               if (fakeent)
+                       free(fakeent);
                fakeent = xmalloc(sizeof(*fakeent) + entlen);
                memcpy(fakeent->base, objdir, objdir_len);
                fakeent->name = fakeent->base + objdir_len + 1;
                fakeent->name[-1] = '/';
+               if (last_objdir)
+                       free((char *) last_objdir);
+               last_objdir = strdup(objdir);
        }
        fakeent->next = alt_odb_list;