git-p4: Unset P4DIFF environment variable when using 'p4 -du diff'
[gitweb.git] / remote.c
index 0012954b6f795d75d442f4c58f29dc194888d022..f3f7375eea6d8c09e4ab6f561be22b08e545efcb 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -2,9 +2,14 @@
 #include "remote.h"
 #include "refs.h"
 
+struct counted_string {
+       size_t len;
+       const char *s;
+};
 struct rewrite {
        const char *base;
-       const char **instead_of;
+       size_t baselen;
+       struct counted_string *instead_of;
        int instead_of_nr;
        int instead_of_alloc;
 };
@@ -30,21 +35,32 @@ static char buffer[BUF_SIZE];
 static const char *alias_url(const char *url)
 {
        int i, j;
+       char *ret;
+       struct counted_string *longest;
+       int longest_i;
+
+       longest = NULL;
+       longest_i = -1;
        for (i = 0; i < rewrite_nr; i++) {
                if (!rewrite[i])
                        continue;
                for (j = 0; j < rewrite[i]->instead_of_nr; j++) {
-                       if (!prefixcmp(url, rewrite[i]->instead_of[j])) {
-                               char *ret = malloc(strlen(rewrite[i]->base) -
-                                                  strlen(rewrite[i]->instead_of[j]) +
-                                                  strlen(url) + 1);
-                               strcpy(ret, rewrite[i]->base);
-                               strcat(ret, url + strlen(rewrite[i]->instead_of[j]));
-                               return ret;
+                       if (!prefixcmp(url, rewrite[i]->instead_of[j].s) &&
+                           (!longest ||
+                            longest->len < rewrite[i]->instead_of[j].len)) {
+                               longest = &(rewrite[i]->instead_of[j]);
+                               longest_i = i;
                        }
                }
        }
-       return url;
+       if (!longest)
+               return url;
+
+       ret = malloc(rewrite[longest_i]->baselen +
+                    (strlen(url) - longest->len) + 1);
+       strcpy(ret, rewrite[longest_i]->base);
+       strcpy(ret + rewrite[longest_i]->baselen, url + longest->len);
+       return ret;
 }
 
 static void add_push_refspec(struct remote *remote, const char *ref)
@@ -137,27 +153,33 @@ static struct rewrite *make_rewrite(const char *base, int len)
        int i;
 
        for (i = 0; i < rewrite_nr; i++) {
-               if (len ? (!strncmp(base, rewrite[i]->base, len) &&
-                          !rewrite[i]->base[len]) :
-                   !strcmp(base, rewrite[i]->base))
+               if (len
+                   ? (len == rewrite[i]->baselen &&
+                      !strncmp(base, rewrite[i]->base, len))
+                   : !strcmp(base, rewrite[i]->base))
                        return rewrite[i];
        }
 
        ALLOC_GROW(rewrite, rewrite_nr + 1, rewrite_alloc);
        ret = xcalloc(1, sizeof(struct rewrite));
        rewrite[rewrite_nr++] = ret;
-       if (len)
+       if (len) {
                ret->base = xstrndup(base, len);
-       else
+               ret->baselen = len;
+       }
+       else {
                ret->base = xstrdup(base);
-
+               ret->baselen = strlen(base);
+       }
        return ret;
 }
 
 static void add_instead_of(struct rewrite *rewrite, const char *instead_of)
 {
        ALLOC_GROW(rewrite->instead_of, rewrite->instead_of_nr + 1, rewrite->instead_of_alloc);
-       rewrite->instead_of[rewrite->instead_of_nr++] = instead_of;
+       rewrite->instead_of[rewrite->instead_of_nr].s = instead_of;
+       rewrite->instead_of[rewrite->instead_of_nr].len = strlen(instead_of);
+       rewrite->instead_of_nr++;
 }
 
 static void read_remotes_file(struct remote *remote)
@@ -335,7 +357,8 @@ static int handle_config(const char *key, const char *value)
                        remote->fetch_tags = -1;
        } else if (!strcmp(subkey, ".proxy")) {
                remote->http_proxy = xstrdup(value);
-       }
+       } else if (!strcmp(subkey, ".skipdefaultupdate"))
+               remote->skip_default_update = 1;
        return 0;
 }
 
@@ -571,8 +594,7 @@ void free_refs(struct ref *ref)
        struct ref *next;
        while (ref) {
                next = ref->next;
-               if (ref->peer_ref)
-                       free(ref->peer_ref);
+               free(ref->peer_ref);
                free(ref);
                ref = next;
        }
@@ -708,9 +730,17 @@ static int match_explicit(struct ref *src, struct ref *dst,
                errs = 1;
 
        if (!dst_value) {
+               unsigned char sha1[20];
+               int flag;
+
                if (!matched_src)
                        return errs;
-               dst_value = matched_src->name;
+               dst_value = resolve_ref(matched_src->name, sha1, 1, &flag);
+               if (!dst_value ||
+                   ((flag & REF_ISSYMREF) &&
+                    prefixcmp(dst_value, "refs/heads/")))
+                       die("%s cannot be resolved to branch.",
+                           matched_src->name);
        }
 
        switch (count_refspec_match(dst_value, dst, &matched_dst)) {