Code

Merge branch 'sp/maint-dumb-http-pack-reidx' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 16 Jun 2010 23:21:30 +0000 (16:21 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 16 Jun 2010 23:21:30 +0000 (16:21 -0700)
* sp/maint-dumb-http-pack-reidx:
  http.c::new_http_pack_request: do away with the temp variable filename
  http-fetch: Use temporary files for pack-*.idx until verified
  http-fetch: Use index-pack rather than verify-pack to check packs
  Allow parse_pack_index on temporary files
  Extract verify_pack_index for reuse from verify_pack
  Introduce close_pack_index to permit replacement
  http.c: Remove unnecessary strdup of sha1_to_hex result
  http.c: Don't store destination name in request structures
  http.c: Drop useless != NULL test in finish_http_pack_request
  http.c: Tiny refactoring of finish_http_pack_request
  t5550-http-fetch: Use subshell for repository operations
  http.c: Remove bad free of static block

1  2 
cache.h
http-walker.c
http.c
http.h
pack.h
sha1_file.c

diff --combined cache.h
index 5eb0573bcc81050cc06a304f346fe5f41ebe242e,7db23eff26a7f42d2a92f8f7023e22bad3f4e661..0d101e4913f380a0eda0b3bf9e1d8b76e34c6fd8
+++ b/cache.h
@@@ -387,9 -387,6 +387,9 @@@ static inline enum object_type object_t
  #define ATTRIBUTE_MACRO_PREFIX "[attr]"
  #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
  #define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
 +#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
 +#define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF"
 +#define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE"
  
  /*
   * Repository-local GIT_* environment variables
@@@ -691,7 -688,6 +691,7 @@@ int normalize_path_copy(char *dst, cons
  int longest_ancestor_length(const char *path, const char *prefix_list);
  char *strip_path_suffix(const char *path, const char *suffix);
  int daemon_avoid_alias(const char *path);
 +int offset_1st_component(const char *path);
  
  /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
  extern int sha1_object_info(const unsigned char *, unsigned long *);
@@@ -701,7 -697,7 +701,7 @@@ static inline void *read_sha1_file(cons
        return read_sha1_file_repl(sha1, type, size, NULL);
  }
  extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
 -extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
 +extern int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
  extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
  extern int force_object_loose(const unsigned char *sha1, time_t mtime);
  
@@@ -894,7 -890,6 +894,7 @@@ struct ref 
  extern struct ref *find_ref_by_name(const struct ref *list, const char *name);
  
  #define CONNECT_VERBOSE       (1u << 0)
 +extern char *git_getpass(const char *prompt);
  extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
  extern int finish_connect(struct child_process *conn);
  extern int path_match(const char *path, int nr, char **match);
@@@ -905,7 -900,7 +905,7 @@@ struct extra_have_objects 
  extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags, struct extra_have_objects *);
  extern int server_supports(const char *feature);
  
- extern struct packed_git *parse_pack_index(unsigned char *sha1);
+ extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
  
  extern void prepare_packed_git(void);
  extern void reprepare_packed_git(void);
@@@ -916,6 -911,7 +916,7 @@@ extern struct packed_git *find_sha1_pac
  
  extern void pack_report(void);
  extern int open_pack_index(struct packed_git *);
+ extern void close_pack_index(struct packed_git *);
  extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
  extern void close_pack_windows(struct packed_git *);
  extern void unuse_pack(struct pack_window **);
@@@ -1058,7 -1054,4 +1059,7 @@@ void overlay_tree_on_cache(const char *
  char *alias_lookup(const char *alias);
  int split_cmdline(char *cmdline, const char ***argv);
  
 +/* builtin/merge.c */
 +int checkout_fast_forward(const unsigned char *from, const unsigned char *to);
 +
  #endif /* CACHE_H */
diff --combined http-walker.c
index ef99ae647ae02995495c71455eef785bdeca1789,3a726dea0864878644d34fdc5f0afa8e6e633c95..8ca76d0507bdc1d95283e1f5fee3f88180cdce26
@@@ -510,7 -510,7 +510,7 @@@ static int fetch_object(struct walker *
                ret = error("File %s has bad hash", hex);
        } else if (req->rename < 0) {
                ret = error("unable to write sha1 filename %s",
-                           req->filename);
+                           sha1_file_name(req->sha1));
        }
  
        release_http_object_request(req);
@@@ -543,30 -543,17 +543,30 @@@ static int fetch_ref(struct walker *wal
  
  static void cleanup(struct walker *walker)
  {
 -      http_cleanup();
 +      struct walker_data *data = walker->data;
 +      struct alt_base *alt, *alt_next;
 +
 +      if (data) {
 +              alt = data->alt;
 +              while (alt) {
 +                      alt_next = alt->next;
 +
 +                      free(alt->base);
 +                      free(alt);
 +
 +                      alt = alt_next;
 +              }
 +              free(data);
 +              walker->data = NULL;
 +      }
  }
  
 -struct walker *get_http_walker(const char *url, struct remote *remote)
 +struct walker *get_http_walker(const char *url)
  {
        char *s;
        struct walker_data *data = xmalloc(sizeof(struct walker_data));
        struct walker *walker = xmalloc(sizeof(struct walker));
  
 -      http_init(remote);
 -
        data->alt = xmalloc(sizeof(*data->alt));
        data->alt->base = xmalloc(strlen(url) + 1);
        strcpy(data->alt->base, url);
diff --combined http.c
index 364c333c6b9c553121c4cc6ad6a9b622de185808,e41fcc380034943d1f7bd80661febd42af6f4104..901e5972970e672f2524d70d11d4c3bb74ce98c5
--- 1/http.c
--- 2/http.c
+++ b/http.c
@@@ -1,6 -1,7 +1,7 @@@
  #include "http.h"
  #include "pack.h"
  #include "sideband.h"
+ #include "run-command.h"
  
  int data_received;
  int active_requests;
@@@ -204,7 -205,7 +205,7 @@@ static void init_curl_http_auth(CURL *r
        if (user_name) {
                struct strbuf up = STRBUF_INIT;
                if (!user_pass)
 -                      user_pass = xstrdup(getpass("Password: "));
 +                      user_pass = xstrdup(git_getpass("Password: "));
                strbuf_addf(&up, "%s:%s", user_name, user_pass);
                curl_easy_setopt(result, CURLOPT_USERPWD,
                                 strbuf_detach(&up, NULL));
@@@ -219,7 -220,7 +220,7 @@@ static int has_cert_password(void
                return 0;
        /* Only prompt the user once. */
        ssl_cert_password_required = -1;
 -      ssl_cert_password = getpass("Certificate Password: ");
 +      ssl_cert_password = git_getpass("Certificate Password: ");
        if (ssl_cert_password != NULL) {
                ssl_cert_password = xstrdup(ssl_cert_password);
                return 1;
@@@ -720,7 -721,7 +721,7 @@@ static inline int hex(int v
                return 'A' + v - 10;
  }
  
 -static void end_url_with_slash(struct strbuf *buf, const char *url)
 +void end_url_with_slash(struct strbuf *buf, const char *url)
  {
        strbuf_addstr(buf, url);
        if (buf->len && buf->buf[buf->len - 1] != '/')
@@@ -896,47 -897,67 +897,67 @@@ int http_fetch_ref(const char *base, st
  }
  
  /* Helpers for fetching packs */
- static int fetch_pack_index(unsigned char *sha1, const char *base_url)
+ static char *fetch_pack_index(unsigned char *sha1, const char *base_url)
  {
-       int ret = 0;
-       char *hex = xstrdup(sha1_to_hex(sha1));
-       char *filename;
-       char *url = NULL;
+       char *url, *tmp;
        struct strbuf buf = STRBUF_INIT;
  
-       if (has_pack_index(sha1)) {
-               ret = 0;
-               goto cleanup;
-       }
        if (http_is_verbose)
-               fprintf(stderr, "Getting index for pack %s\n", hex);
+               fprintf(stderr, "Getting index for pack %s\n", sha1_to_hex(sha1));
  
        end_url_with_slash(&buf, base_url);
-       strbuf_addf(&buf, "objects/pack/pack-%s.idx", hex);
+       strbuf_addf(&buf, "objects/pack/pack-%s.idx", sha1_to_hex(sha1));
        url = strbuf_detach(&buf, NULL);
  
-       filename = sha1_pack_index_name(sha1);
-       if (http_get_file(url, filename, 0) != HTTP_OK)
-               ret = error("Unable to get pack index %s\n", url);
+       strbuf_addf(&buf, "%s.temp", sha1_pack_index_name(sha1));
+       tmp = strbuf_detach(&buf, NULL);
+       if (http_get_file(url, tmp, 0) != HTTP_OK) {
+               error("Unable to get pack index %s\n", url);
+               free(tmp);
+               tmp = NULL;
+       }
  
- cleanup:
-       free(hex);
        free(url);
-       return ret;
+       return tmp;
  }
  
  static int fetch_and_setup_pack_index(struct packed_git **packs_head,
        unsigned char *sha1, const char *base_url)
  {
        struct packed_git *new_pack;
+       char *tmp_idx = NULL;
+       int ret;
  
-       if (fetch_pack_index(sha1, base_url))
+       if (has_pack_index(sha1)) {
+               new_pack = parse_pack_index(sha1, NULL);
+               if (!new_pack)
+                       return -1; /* parse_pack_index() already issued error message */
+               goto add_pack;
+       }
+       tmp_idx = fetch_pack_index(sha1, base_url);
+       if (!tmp_idx)
                return -1;
  
-       new_pack = parse_pack_index(sha1);
-       if (!new_pack)
+       new_pack = parse_pack_index(sha1, tmp_idx);
+       if (!new_pack) {
+               unlink(tmp_idx);
+               free(tmp_idx);
                return -1; /* parse_pack_index() already issued error message */
+       }
+       ret = verify_pack_index(new_pack);
+       if (!ret) {
+               close_pack_index(new_pack);
+               ret = move_temp_to_file(tmp_idx, sha1_pack_index_name(sha1));
+       }
+       free(tmp_idx);
+       if (ret)
+               return -1;
+ add_pack:
        new_pack->next = *packs_head;
        *packs_head = new_pack;
        return 0;
@@@ -1000,37 -1021,62 +1021,62 @@@ void release_http_pack_request(struct h
  
  int finish_http_pack_request(struct http_pack_request *preq)
  {
-       int ret;
        struct packed_git **lst;
+       struct packed_git *p = preq->target;
+       char *tmp_idx;
+       struct child_process ip;
+       const char *ip_argv[8];
  
-       preq->target->pack_size = ftell(preq->packfile);
+       close_pack_index(p);
  
-       if (preq->packfile != NULL) {
-               fclose(preq->packfile);
-               preq->packfile = NULL;
-               preq->slot->local = NULL;
-       }
-       ret = move_temp_to_file(preq->tmpfile, preq->filename);
-       if (ret)
-               return ret;
+       fclose(preq->packfile);
+       preq->packfile = NULL;
+       preq->slot->local = NULL;
  
        lst = preq->lst;
-       while (*lst != preq->target)
+       while (*lst != p)
                lst = &((*lst)->next);
        *lst = (*lst)->next;
  
-       if (verify_pack(preq->target))
+       tmp_idx = xstrdup(preq->tmpfile);
+       strcpy(tmp_idx + strlen(tmp_idx) - strlen(".pack.temp"),
+              ".idx.temp");
+       ip_argv[0] = "index-pack";
+       ip_argv[1] = "-o";
+       ip_argv[2] = tmp_idx;
+       ip_argv[3] = preq->tmpfile;
+       ip_argv[4] = NULL;
+       memset(&ip, 0, sizeof(ip));
+       ip.argv = ip_argv;
+       ip.git_cmd = 1;
+       ip.no_stdin = 1;
+       ip.no_stdout = 1;
+       if (run_command(&ip)) {
+               unlink(preq->tmpfile);
+               unlink(tmp_idx);
+               free(tmp_idx);
+               return -1;
+       }
+       unlink(sha1_pack_index_name(p->sha1));
+       if (move_temp_to_file(preq->tmpfile, sha1_pack_name(p->sha1))
+        || move_temp_to_file(tmp_idx, sha1_pack_index_name(p->sha1))) {
+               free(tmp_idx);
                return -1;
-       install_packed_git(preq->target);
+       }
  
+       install_packed_git(p);
+       free(tmp_idx);
        return 0;
  }
  
  struct http_pack_request *new_http_pack_request(
        struct packed_git *target, const char *base_url)
  {
-       char *filename;
        long prev_posn = 0;
        char range[RANGE_HEADER_SIZE];
        struct strbuf buf = STRBUF_INIT;
                sha1_to_hex(target->sha1));
        preq->url = strbuf_detach(&buf, NULL);
  
-       filename = sha1_pack_name(target->sha1);
-       snprintf(preq->filename, sizeof(preq->filename), "%s", filename);
-       snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp", filename);
+       snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp",
+               sha1_pack_name(target->sha1));
        preq->packfile = fopen(preq->tmpfile, "a");
        if (!preq->packfile) {
                error("Unable to open local file %s for pack",
        return preq;
  
  abort:
-       free(filename);
        free(preq->url);
        free(preq);
        return NULL;
@@@ -1137,7 -1181,6 +1181,6 @@@ struct http_object_request *new_http_ob
        freq->localfile = -1;
  
        filename = sha1_file_name(sha1);
-       snprintf(freq->filename, sizeof(freq->filename), "%s", filename);
        snprintf(freq->tmpfile, sizeof(freq->tmpfile),
                 "%s.temp", filename);
  
        }
  
        if (freq->localfile < 0) {
-               error("Couldn't create temporary file %s for %s: %s",
-                     freq->tmpfile, freq->filename, strerror(errno));
+               error("Couldn't create temporary file %s: %s",
+                     freq->tmpfile, strerror(errno));
                goto abort;
        }
  
                        prev_posn = 0;
                        lseek(freq->localfile, 0, SEEK_SET);
                        if (ftruncate(freq->localfile, 0) < 0) {
-                               error("Couldn't truncate temporary file %s for %s: %s",
-                                         freq->tmpfile, freq->filename, strerror(errno));
+                               error("Couldn't truncate temporary file %s: %s",
+                                         freq->tmpfile, strerror(errno));
                                goto abort;
                        }
                }
@@@ -1291,7 -1334,7 +1334,7 @@@ int finish_http_object_request(struct h
                return -1;
        }
        freq->rename =
-               move_temp_to_file(freq->tmpfile, freq->filename);
+               move_temp_to_file(freq->tmpfile, sha1_file_name(freq->sha1));
  
        return freq->rename;
  }
diff --combined http.h
index c78cacb9c3543caf1f59b9068cac2b053ef088f9,84bdbd0f76787090a1ec511a006b1c9885521d71..b431b8bd5b6d694dd01fc92b2ffcca41655d82bf
--- 1/http.h
--- 2/http.h
+++ b/http.h
@@@ -117,7 -117,6 +117,7 @@@ extern void append_remote_object_url(st
                                     int only_two_digit_prefix);
  extern char *get_remote_object_url(const char *url, const char *hex,
                                   int only_two_digit_prefix);
 +extern void end_url_with_slash(struct strbuf *buf, const char *url);
  
  /* Options for http_request_*() */
  #define HTTP_NO_CACHE         1
@@@ -153,7 -152,6 +153,6 @@@ struct http_pack_reques
        struct packed_git *target;
        struct packed_git **lst;
        FILE *packfile;
-       char filename[PATH_MAX];
        char tmpfile[PATH_MAX];
        struct curl_slist *range_header;
        struct active_request_slot *slot;
@@@ -168,7 -166,6 +167,6 @@@ extern void release_http_pack_request(s
  struct http_object_request
  {
        char *url;
-       char filename[PATH_MAX];
        char tmpfile[PATH_MAX];
        int localfile;
        CURLcode curl_result;
diff --combined pack.h
index d268c014c9eb7040bd65125b13d68edce670274b,880f9c2930c98ee1cd28f8143a2dc94f10d4f530..bb275762b7eb6f473f333ae40780821e383db20b
--- 1/pack.h
--- 2/pack.h
+++ b/pack.h
@@@ -57,10 -57,10 +57,11 @@@ struct pack_idx_entry 
  
  extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);
  extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
+ extern int verify_pack_index(struct packed_git *);
  extern int verify_pack(struct packed_git *);
  extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);
  extern char *index_pack_lockfile(int fd);
 +extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned char *);
  
  #define PH_ERROR_EOF          (-1)
  #define PH_ERROR_PACK_SIGNATURE       (-2)
diff --combined sha1_file.c
index 1b551e4609dfde6f047de54c4ee7ed4b006c0ce5,9f3f514e713cf7d1e2efdbe5de093671cc6b8fdf..1efa9154eda4e1ec064d627dfb21c876c914f4d7
@@@ -35,6 -35,13 +35,6 @@@ static size_t sz_fmt(size_t s) { retur
  
  const unsigned char null_sha1[20];
  
 -static inline int offset_1st_component(const char *path)
 -{
 -      if (has_dos_drive_prefix(path))
 -              return 2 + (path[2] == '/');
 -      return *path == '/';
 -}
 -
  int safe_create_leading_directories(char *path)
  {
        char *pos = path + offset_1st_component(path);
@@@ -599,6 -606,14 +599,14 @@@ void unuse_pack(struct pack_window **w_
        }
  }
  
+ void close_pack_index(struct packed_git *p)
+ {
+       if (p->index_data) {
+               munmap((void *)p->index_data, p->index_size);
+               p->index_data = NULL;
+       }
+ }
  /*
   * This is used by git-repack in case a newly created pack happens to
   * contain the same set of objects as an existing one.  In that case
@@@ -620,8 -635,7 +628,7 @@@ void free_pack_by_name(const char *pack
                        close_pack_windows(p);
                        if (p->pack_fd != -1)
                                close(p->pack_fd);
-                       if (p->index_data)
-                               munmap((void *)p->index_data, p->index_size);
+                       close_pack_index(p);
                        free(p->bad_object_sha1);
                        *pp = p->next;
                        free(p);
@@@ -831,9 -845,8 +838,8 @@@ struct packed_git *add_packed_git(cons
        return p;
  }
  
- struct packed_git *parse_pack_index(unsigned char *sha1)
+ struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
  {
-       const char *idx_path = sha1_pack_index_name(sha1);
        const char *path = sha1_pack_name(sha1);
        struct packed_git *p = alloc_packed_git(strlen(path) + 1);
  
@@@ -2271,7 -2284,7 +2277,7 @@@ static int create_tmpfile(char *buffer
  }
  
  static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
 -                            void *buf, unsigned long len, time_t mtime)
 +                            const void *buf, unsigned long len, time_t mtime)
  {
        int fd, ret;
        unsigned char compressed[4096];
        git_SHA1_Update(&c, hdr, hdrlen);
  
        /* Then the data itself.. */
 -      stream.next_in = buf;
 +      stream.next_in = (void *)buf;
        stream.avail_in = len;
        do {
                unsigned char *in0 = stream.next_in;
        return move_temp_to_file(tmpfile, filename);
  }
  
 -int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
 +int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
  {
        unsigned char sha1[20];
        char hdr[32];
@@@ -2448,8 -2461,6 +2454,8 @@@ int index_fd(unsigned char *sha1, int f
                else
                        ret = -1;
                strbuf_release(&sbuf);
 +      } else if (!size) {
 +              ret = index_mem(sha1, NULL, size, write_object, type, path);
        } else if (size <= SMALL_FILE_SIZE) {
                char *buf = xmalloc(size);
                if (size == read_in_full(fd, buf, size))
                else
                        ret = error("short read %s", strerror(errno));
                free(buf);
 -      } else if (size) {
 +      } else {
                void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
                ret = index_mem(sha1, buf, size, write_object, type, path);
                munmap(buf, size);
 -      } else
 -              ret = index_mem(sha1, NULL, size, write_object, type, path);
 +      }
        close(fd);
        return ret;
  }