Merge branch 'jc/shared-literally'
authorJunio C Hamano <gitster@pobox.com>
Mon, 6 Apr 2009 07:42:52 +0000 (00:42 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 6 Apr 2009 07:42:52 +0000 (00:42 -0700)
* jc/shared-literally:
t1301: loosen test for forced modes
set_shared_perm(): sometimes we know what the final mode bits should look like
move_temp_to_file(): do not forget to chmod() in "Coda hack" codepath
Move chmod(foo, 0444) into move_temp_to_file()
"core.sharedrepository = 0mode" should set, not loosen

1  2 
builtin-init-db.c
cache.h
fast-import.c
http-push.c
index-pack.c
sha1_file.c
t/t1301-shared-repo.sh
diff --combined builtin-init-db.c
index fc63d0fce5d3067bec884ac3ccaf12e0fd0d4468,8199e5d4d5168859363b7a644535fd0cb01a1441..4e02b33bb77b8957940562f87bc0b6faaeb3a101
@@@ -130,7 -130,8 +130,7 @@@ static void copy_templates(const char *
        }
        dir = opendir(template_path);
        if (!dir) {
 -              fprintf(stderr, "warning: templates not found %s\n",
 -                      template_dir);
 +              warning("templates not found %s", template_dir);
                return;
        }
  
  
        if (repository_format_version &&
            repository_format_version != GIT_REPO_VERSION) {
 -              fprintf(stderr, "warning: not copying templates of "
 -                      "a wrong format version %d from '%s'\n",
 +              warning("not copying templates of "
 +                      "a wrong format version %d from '%s'",
                        repository_format_version,
                        template_dir);
                closedir(dir);
@@@ -194,6 -195,8 +194,8 @@@ static int create_default_files(const c
  
        git_config(git_default_config, NULL);
        is_bare_repository_cfg = init_is_bare_repository;
+       /* reading existing config may have overwrote it */
        if (init_shared_repository != -1)
                shared_repository = init_shared_repository;
  
@@@ -312,12 -315,15 +314,15 @@@ int init_db(const char *template_dir, u
                 * and compatibility values for PERM_GROUP and
                 * PERM_EVERYBODY.
                 */
-               if (shared_repository == PERM_GROUP)
+               if (shared_repository < 0)
+                       /* force to the mode value */
+                       sprintf(buf, "0%o", -shared_repository);
+               else if (shared_repository == PERM_GROUP)
                        sprintf(buf, "%d", OLD_PERM_GROUP);
                else if (shared_repository == PERM_EVERYBODY)
                        sprintf(buf, "%d", OLD_PERM_EVERYBODY);
                else
-                       sprintf(buf, "0%o", shared_repository);
+                       die("oops");
                git_config_set("core.sharedrepository", buf);
                git_config_set("receive.denyNonFastforwards", "true");
        }
@@@ -397,6 -403,9 +402,9 @@@ int cmd_init_db(int argc, const char **
                        usage(init_db_usage);
        }
  
+       if (init_shared_repository != -1)
+               shared_repository = init_shared_repository;
        /*
         * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
         * without --bare.  Catch the error early.
diff --combined cache.h
index 9cf5a13c2cbec321aa728f5024a48e3291fb697d,e283bbe1736ad7ba321c815b48e58cb41e781e16..61664addd76829c09282e0d0d7e7b4f347900bd7
+++ b/cache.h
@@@ -140,8 -140,8 +140,8 @@@ struct ondisk_cache_entry_extended 
  };
  
  struct cache_entry {
 -      unsigned int ce_ctime;
 -      unsigned int ce_mtime;
 +      struct cache_time ce_ctime;
 +      struct cache_time ce_mtime;
        unsigned int ce_dev;
        unsigned int ce_ino;
        unsigned int ce_mode;
@@@ -282,7 -282,7 +282,7 @@@ struct index_state 
        struct cache_entry **cache;
        unsigned int cache_nr, cache_alloc, cache_changed;
        struct cache_tree *cache_tree;
 -      time_t timestamp;
 +      struct cache_time timestamp;
        void *alloc;
        unsigned name_hash_initialized : 1,
                 initialized : 1;
@@@ -428,7 -428,7 +428,7 @@@ extern int read_index_preload(struct in
  extern int read_index_from(struct index_state *, const char *path);
  extern int is_index_unborn(struct index_state *);
  extern int read_index_unmerged(struct index_state *);
 -extern int write_index(const struct index_state *, int newfd);
 +extern int write_index(struct index_state *, int newfd);
  extern int discard_index(struct index_state *);
  extern int unmerged_index(const struct index_state *);
  extern int verify_path(const char *path);
@@@ -443,7 -443,6 +443,7 @@@ extern int add_index_entry(struct index
  extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
  extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
  extern int remove_index_entry_at(struct index_state *, int pos);
 +extern void remove_marked_cache_entries(struct index_state *istate);
  extern int remove_file_from_index(struct index_state *, const char *path);
  #define ADD_CACHE_VERBOSE 1
  #define ADD_CACHE_PRETEND 2
@@@ -542,17 -541,8 +542,17 @@@ enum rebase_setup_type 
        AUTOREBASE_ALWAYS,
  };
  
 +enum push_default_type {
 +      PUSH_DEFAULT_UNSPECIFIED = -1,
 +      PUSH_DEFAULT_NOTHING = 0,
 +      PUSH_DEFAULT_MATCHING,
 +      PUSH_DEFAULT_TRACKING,
 +      PUSH_DEFAULT_CURRENT,
 +};
 +
  extern enum branch_track git_branch_track;
  extern enum rebase_setup_type autorebase;
 +extern enum push_default_type push_default;
  
  #define GIT_REPO_VERSION 0
  extern int repository_format_version;
@@@ -623,7 -613,8 +623,8 @@@ enum sharedrepo 
        PERM_EVERYBODY      = 0664,
  };
  int git_config_perm(const char *var, const char *value);
- int adjust_shared_perm(const char *path);
+ int set_shared_perm(const char *path, int mode);
+ #define adjust_shared_perm(path) set_shared_perm((path), 0)
  int safe_create_leading_directories(char *path);
  int safe_create_leading_directories_const(const char *path);
  char *enter_repo(char *path, int strict);
@@@ -654,7 -645,7 +655,7 @@@ extern int check_sha1_signature(const u
  
  extern int move_temp_to_file(const char *tmpfile, const char *filename);
  
 -extern int has_sha1_pack(const unsigned char *sha1, const char **ignore);
 +extern int has_sha1_pack(const unsigned char *sha1);
  extern int has_sha1_file(const unsigned char *sha1);
  extern int has_loose_object_nonlocal(const unsigned char *sha1);
  
@@@ -734,13 -725,11 +735,13 @@@ struct checkout 
  };
  
  extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
 -extern int has_symlink_leading_path(int len, const char *name);
 -extern int has_symlink_or_noent_leading_path(int len, const char *name);
 -extern int has_dirs_only_path(int len, const char *name, int prefix_len);
 -extern void invalidate_lstat_cache(int len, const char *name);
 +extern int has_symlink_leading_path(const char *name, int len);
 +extern int has_symlink_or_noent_leading_path(const char *name, int len);
 +extern int has_dirs_only_path(const char *name, int len, int prefix_len);
 +extern void invalidate_lstat_cache(const char *name, int len);
  extern void clear_lstat_cache(void);
 +extern void schedule_dir_for_removal(const char *name, int len);
 +extern void remove_scheduled_dirs(void);
  
  extern struct alternate_object_database {
        struct alternate_object_database *next;
@@@ -813,7 -802,7 +814,7 @@@ struct ref 
  #define REF_HEADS     (1u << 1)
  #define REF_TAGS      (1u << 2)
  
 -extern struct ref *find_ref_by_name(struct ref *list, const char *name);
 +extern struct ref *find_ref_by_name(const struct ref *list, const char *name);
  
  #define CONNECT_VERBOSE       (1u << 0)
  extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
@@@ -851,6 -840,7 +852,6 @@@ extern void *unpack_entry(struct packed
  extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
  extern unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
  extern const char *packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
 -extern int matches_pack_name(struct packed_git *p, const char *name);
  
  /* Dumb servers support */
  extern int update_server_info(int);
diff --combined fast-import.c
index db44da3e096fcd7cb5cc1664b1d9881535585591,d5fc042bbfe97080df3e275f069055c63bad32eb..23c496d6839646ec61a7172f83c86e244463498f
@@@ -1,5 -1,4 +1,5 @@@
  /*
 +(See Documentation/git-fast-import.txt for maintained documentation.)
  Format of STDIN stream:
  
    stream ::= cmd*;
@@@ -19,8 -18,8 +19,8 @@@
  
    new_commit ::= 'commit' sp ref_str lf
      mark?
 -    ('author' sp name '<' email '>' when lf)?
 -    'committer' sp name '<' email '>' when lf
 +    ('author' sp name sp '<' email '>' sp when lf)?
 +    'committer' sp name sp '<' email '>' sp when lf
      commit_msg
      ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
      ('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)*
@@@ -44,7 -43,7 +44,7 @@@
  
    new_tag ::= 'tag' sp tag_str lf
      'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
 -    ('tagger' sp name '<' email '>' when lf)?
 +    ('tagger' sp name sp '<' email '>' sp when lf)?
      tag_msg;
    tag_msg ::= data;
  
@@@ -903,9 -902,6 +903,6 @@@ static char *keep_pack(char *curr_index
        static const char *keep_msg = "fast-import";
        int keep_fd;
  
-       chmod(pack_data->pack_name, 0444);
-       chmod(curr_index_name, 0444);
        keep_fd = odb_pack_keep(name, sizeof(name), pack_data->sha1);
        if (keep_fd < 0)
                die("cannot create keep file");
@@@ -1746,19 -1742,21 +1743,19 @@@ static void parse_data(struct strbuf *s
  static int validate_raw_date(const char *src, char *result, int maxlen)
  {
        const char *orig_src = src;
 -      char *endp, sign;
 -      unsigned long date;
 +      char *endp;
  
        errno = 0;
  
 -      date = strtoul(src, &endp, 10);
 +      strtoul(src, &endp, 10);
        if (errno || endp == src || *endp != ' ')
                return -1;
  
        src = endp + 1;
        if (*src != '-' && *src != '+')
                return -1;
 -      sign = *src;
  
 -      date = strtoul(src + 1, &endp, 10);
 +      strtoul(src + 1, &endp, 10);
        if (errno || endp == src || *endp || (endp - orig_src) >= maxlen)
                return -1;
  
diff --combined http-push.c
index 6ce5a1d550d4cf781673c62599bd681fc5e318b5,968b6b0662a89d437e53bcc699c65e98a745f659..e465b20c1acd3f94adb059f39709f05a1daddf9e
@@@ -97,7 -97,7 +97,7 @@@ struct rep
        struct remote_lock *locks;
  };
  
 -static struct repo *remote;
 +static struct repo *repo;
  
  enum transfer_state {
        NEED_FETCH,
@@@ -324,7 -324,7 +324,7 @@@ static void start_fetch_loose(struct tr
  
        git_SHA1_Init(&request->c);
  
 -      url = get_remote_object_url(remote->url, hex, 0);
 +      url = get_remote_object_url(repo->url, hex, 0);
        request->url = xstrdup(url);
  
        /* If a previous temp file is present, process what was already
        request->state = RUN_FETCH_LOOSE;
        if (!start_active_slot(slot)) {
                fprintf(stderr, "Unable to start GET request\n");
 -              remote->can_update_info_refs = 0;
 +              repo->can_update_info_refs = 0;
                release_request(request);
        }
  }
@@@ -399,7 -399,7 +399,7 @@@ static void start_mkcol(struct transfer
        char *hex = sha1_to_hex(request->obj->sha1);
        struct active_request_slot *slot;
  
 -      request->url = get_remote_object_url(remote->url, hex, 1);
 +      request->url = get_remote_object_url(repo->url, hex, 1);
  
        slot = get_active_slot();
        slot->callback_func = process_response;
@@@ -434,10 -434,10 +434,10 @@@ static void start_fetch_packed(struct t
        struct transfer_request *check_request = request_queue_head;
        struct active_request_slot *slot;
  
 -      target = find_sha1_pack(request->obj->sha1, remote->packs);
 +      target = find_sha1_pack(request->obj->sha1, repo->packs);
        if (!target) {
                fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
 -              remote->can_update_info_refs = 0;
 +              repo->can_update_info_refs = 0;
                release_request(request);
                return;
        }
        snprintf(request->tmpfile, sizeof(request->tmpfile),
                 "%s.temp", filename);
  
 -      url = xmalloc(strlen(remote->url) + 64);
 +      url = xmalloc(strlen(repo->url) + 64);
        sprintf(url, "%sobjects/pack/pack-%s.pack",
 -              remote->url, sha1_to_hex(target->sha1));
 +              repo->url, sha1_to_hex(target->sha1));
  
        /* Make sure there isn't another open request for this pack */
        while (check_request) {
        if (!packfile) {
                fprintf(stderr, "Unable to open local file %s for pack",
                        request->tmpfile);
 -              remote->can_update_info_refs = 0;
 +              repo->can_update_info_refs = 0;
                free(url);
                return;
        }
        request->state = RUN_FETCH_PACKED;
        if (!start_active_slot(slot)) {
                fprintf(stderr, "Unable to start GET request\n");
 -              remote->can_update_info_refs = 0;
 +              repo->can_update_info_refs = 0;
                release_request(request);
        }
  }
@@@ -554,10 -554,10 +554,10 @@@ static void start_put(struct transfer_r
        request->buffer.buf.len = stream.total_out;
  
        strbuf_addstr(&buf, "Destination: ");
 -      append_remote_object_url(&buf, remote->url, hex, 0);
 +      append_remote_object_url(&buf, repo->url, hex, 0);
        request->dest = strbuf_detach(&buf, NULL);
  
 -      append_remote_object_url(&buf, remote->url, hex, 0);
 +      append_remote_object_url(&buf, repo->url, hex, 0);
        strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
        request->url = strbuf_detach(&buf, NULL);
  
@@@ -648,7 -648,7 +648,7 @@@ static int refresh_lock(struct remote_l
  
  static void check_locks(void)
  {
 -      struct remote_lock *lock = remote->locks;
 +      struct remote_lock *lock = repo->locks;
        time_t current_time = time(NULL);
        int time_remaining;
  
@@@ -748,7 -748,6 +748,6 @@@ static void finish_request(struct trans
                        aborted = 1;
                }
        } else if (request->state == RUN_FETCH_LOOSE) {
-               fchmod(request->local_fileno, 0444);
                close(request->local_fileno); request->local_fileno = -1;
  
                if (request->curl_result != CURLE_OK &&
                        }
                } else {
                        if (request->http_code == 416)
 -                              fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
 +                              warning("requested range invalid; we may already have all the data.");
  
                        git_inflate_end(&request->stream);
                        git_SHA1_Final(request->real_sha1, &request->c);
                if (request->curl_result != CURLE_OK) {
                        fprintf(stderr, "Unable to get pack file %s\n%s",
                                request->url, curl_errorstr);
 -                      remote->can_update_info_refs = 0;
 +                      repo->can_update_info_refs = 0;
                } else {
                        off_t pack_size = ftell(request->local_stream);
  
                                               request->filename)) {
                                target = (struct packed_git *)request->userData;
                                target->pack_size = pack_size;
 -                              lst = &remote->packs;
 +                              lst = &repo->packs;
                                while (*lst != target)
                                        lst = &((*lst)->next);
                                *lst = (*lst)->next;
                                if (!verify_pack(target))
                                        install_packed_git(target);
                                else
 -                                      remote->can_update_info_refs = 0;
 +                                      repo->can_update_info_refs = 0;
                        }
                }
                release_request(request);
  #ifdef USE_CURL_MULTI
  static int fill_active_slot(void *unused)
  {
 -      struct transfer_request *request = request_queue_head;
 +      struct transfer_request *request;
  
        if (aborted)
                return 0;
@@@ -889,7 -888,7 +888,7 @@@ static int add_send_request(struct obje
                get_remote_object_list(obj->sha1[0]);
        if (obj->flags & (REMOTE | PUSHING))
                return 0;
 -      target = find_sha1_pack(obj->sha1, remote->packs);
 +      target = find_sha1_pack(obj->sha1, repo->packs);
        if (target) {
                obj->flags |= REMOTE;
                return 0;
@@@ -930,8 -929,8 +929,8 @@@ static int fetch_index(unsigned char *s
        struct slot_results results;
  
        /* Don't use the index if the pack isn't there */
 -      url = xmalloc(strlen(remote->url) + 64);
 -      sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
 +      url = xmalloc(strlen(repo->url) + 64);
 +      sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex);
        slot = get_active_slot();
        slot->results = &results;
        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
        if (push_verbosely)
                fprintf(stderr, "Getting index for pack %s\n", hex);
  
 -      sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex);
 +      sprintf(url, "%sobjects/pack/pack-%s.idx", repo->url, hex);
  
        filename = sha1_pack_index_name(sha1);
        snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
@@@ -1018,8 -1017,8 +1017,8 @@@ static int setup_index(unsigned char *s
                return -1;
  
        new_pack = parse_pack_index(sha1);
 -      new_pack->next = remote->packs;
 -      remote->packs = new_pack;
 +      new_pack->next = repo->packs;
 +      repo->packs = new_pack;
        return 0;
  }
  
@@@ -1037,8 -1036,8 +1036,8 @@@ static int fetch_indices(void
        if (push_verbosely)
                fprintf(stderr, "Getting pack list\n");
  
 -      url = xmalloc(strlen(remote->url) + 20);
 -      sprintf(url, "%sobjects/info/packs", remote->url);
 +      url = xmalloc(strlen(repo->url) + 20);
 +      sprintf(url, "%sobjects/info/packs", repo->url);
  
        slot = get_active_slot();
        slot->results = &results;
@@@ -1223,11 -1222,11 +1222,11 @@@ static struct remote_lock *lock_remote(
        struct curl_slist *dav_headers = NULL;
        struct xml_ctx ctx;
  
 -      url = xmalloc(strlen(remote->url) + strlen(path) + 1);
 -      sprintf(url, "%s%s", remote->url, path);
 +      url = xmalloc(strlen(repo->url) + strlen(path) + 1);
 +      sprintf(url, "%s%s", repo->url, path);
  
        /* Make sure leading directories exist for the remote ref */
 -      ep = strchr(url + strlen(remote->url) + 1, '/');
 +      ep = strchr(url + strlen(repo->url) + 1, '/');
        while (ep) {
                char saved_character = ep[1];
                ep[1] = '\0';
        } else {
                lock->url = url;
                lock->start_time = time(NULL);
 -              lock->next = remote->locks;
 -              remote->locks = lock;
 +              lock->next = repo->locks;
 +              repo->locks = lock;
        }
  
        return lock;
@@@ -1330,7 -1329,7 +1329,7 @@@ static int unlock_remote(struct remote_
  {
        struct active_request_slot *slot;
        struct slot_results results;
 -      struct remote_lock *prev = remote->locks;
 +      struct remote_lock *prev = repo->locks;
        struct curl_slist *dav_headers;
        int rc = 0;
  
  
        curl_slist_free_all(dav_headers);
  
 -      if (remote->locks == lock) {
 -              remote->locks = lock->next;
 +      if (repo->locks == lock) {
 +              repo->locks = lock->next;
        } else {
                while (prev && prev->next != lock)
                        prev = prev->next;
  
  static void remove_locks(void)
  {
 -      struct remote_lock *lock = remote->locks;
 +      struct remote_lock *lock = repo->locks;
  
        fprintf(stderr, "Removing remote locks...\n");
        while (lock) {
@@@ -1457,7 -1456,7 +1456,7 @@@ static void handle_remote_ls_ctx(struc
                                }
                        }
                        if (path) {
 -                              path += remote->path_len;
 +                              path += repo->path_len;
                                ls->dentry_name = xstrdup(path);
                        }
                } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
@@@ -1480,7 -1479,7 +1479,7 @@@ static void remote_ls(const char *path
                      void (*userFunc)(struct remote_ls_ctx *ls),
                      void *userData)
  {
 -      char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
 +      char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
        struct active_request_slot *slot;
        struct slot_results results;
        struct strbuf in_buffer = STRBUF_INIT;
        ls.userData = userData;
        ls.userFunc = userFunc;
  
 -      sprintf(url, "%s%s", remote->url, path);
 +      sprintf(url, "%s%s", repo->url, path);
  
        strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST);
  
@@@ -1574,7 -1573,7 +1573,7 @@@ static int locking_available(void
        struct xml_ctx ctx;
        int lock_flags = 0;
  
 -      strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url);
 +      strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, repo->url);
  
        dav_headers = curl_slist_append(dav_headers, "Depth: 0");
        dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
        curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
 -      curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
 +      curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
                        }
                        XML_ParserFree(parser);
                        if (!lock_flags)
 -                              error("Error: no DAV locking support on %s",
 -                                    remote->url);
 +                              error("no DAV locking support on %s",
 +                                    repo->url);
  
                } else {
                        error("Cannot access URL %s, return code %d",
 -                            remote->url, results.curl_result);
 +                            repo->url, results.curl_result);
                        lock_flags = 0;
                }
        } else {
 -              error("Unable to start PROPFIND request on %s", remote->url);
 +              error("Unable to start PROPFIND request on %s", repo->url);
        }
  
        strbuf_release(&out_buffer.buf);
@@@ -1792,8 -1791,21 +1791,8 @@@ static int update_remote(unsigned char 
        return 1;
  }
  
 -static struct ref *local_refs, **local_tail;
  static struct ref *remote_refs, **remote_tail;
  
 -static int one_local_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 -{
 -      struct ref *ref;
 -      int len = strlen(refname) + 1;
 -      ref = xcalloc(1, sizeof(*ref) + len);
 -      hashcpy(ref->new_sha1, sha1);
 -      memcpy(ref->name, refname, len);
 -      *local_tail = ref;
 -      local_tail = &ref->next;
 -      return 0;
 -}
 -
  static void one_remote_ref(char *refname)
  {
        struct ref *ref;
  
        ref = alloc_ref(refname);
  
 -      if (http_fetch_ref(remote->url, ref) != 0) {
 +      if (http_fetch_ref(repo->url, ref) != 0) {
                fprintf(stderr,
                        "Unable to fetch ref %s from %s\n",
 -                      refname, remote->url);
 +                      refname, repo->url);
                free(ref);
                return;
        }
         * Fetch a copy of the object if it doesn't exist locally - it
         * may be required for updating server info later.
         */
 -      if (remote->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
 +      if (repo->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
                obj = lookup_unknown_object(ref->old_sha1);
                if (obj) {
                        fprintf(stderr, "  fetch %s for %s\n",
        remote_tail = &ref->next;
  }
  
 -static void get_local_heads(void)
 -{
 -      local_tail = &local_refs;
 -      for_each_ref(one_local_ref, NULL);
 -}
 -
  static void get_dav_remote_heads(void)
  {
        remote_tail = &remote_refs;
@@@ -1843,6 -1861,55 +1842,6 @@@ static int is_zero_sha1(const unsigned 
        return 1;
  }
  
 -static void unmark_and_free(struct commit_list *list, unsigned int mark)
 -{
 -      while (list) {
 -              struct commit_list *temp = list;
 -              temp->item->object.flags &= ~mark;
 -              list = temp->next;
 -              free(temp);
 -      }
 -}
 -
 -static int ref_newer(const unsigned char *new_sha1,
 -                   const unsigned char *old_sha1)
 -{
 -      struct object *o;
 -      struct commit *old, *new;
 -      struct commit_list *list, *used;
 -      int found = 0;
 -
 -      /* Both new and old must be commit-ish and new is descendant of
 -       * old.  Otherwise we require --force.
 -       */
 -      o = deref_tag(parse_object(old_sha1), NULL, 0);
 -      if (!o || o->type != OBJ_COMMIT)
 -              return 0;
 -      old = (struct commit *) o;
 -
 -      o = deref_tag(parse_object(new_sha1), NULL, 0);
 -      if (!o || o->type != OBJ_COMMIT)
 -              return 0;
 -      new = (struct commit *) o;
 -
 -      if (parse_commit(new) < 0)
 -              return 0;
 -
 -      used = list = NULL;
 -      commit_list_insert(new, &list);
 -      while (list) {
 -              new = pop_most_recent_commit(&list, TMP_MARK);
 -              commit_list_insert(new, &used);
 -              if (new == old) {
 -                      found = 1;
 -                      break;
 -              }
 -      }
 -      unmark_and_free(list, TMP_MARK);
 -      unmark_and_free(used, TMP_MARK);
 -      return found;
 -}
 -
  static void add_remote_info_ref(struct remote_ls_ctx *ls)
  {
        struct strbuf *buf = (struct strbuf *)ls->userData;
  
        ref = alloc_ref(ls->dentry_name);
  
 -      if (http_fetch_ref(remote->url, ref) != 0) {
 +      if (http_fetch_ref(repo->url, ref) != 0) {
                fprintf(stderr,
                        "Unable to fetch ref %s from %s\n",
 -                      ls->dentry_name, remote->url);
 +                      ls->dentry_name, repo->url);
                aborted = 1;
                free(ref);
                return;
@@@ -1931,12 -1998,12 +1930,12 @@@ static void update_remote_info_refs(str
  
  static int remote_exists(const char *path)
  {
 -      char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
 +      char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
        struct active_request_slot *slot;
        struct slot_results results;
        int ret = -1;
  
 -      sprintf(url, "%s%s", remote->url, path);
 +      sprintf(url, "%s%s", repo->url, path);
  
        slot = get_active_slot();
        slot->results = &results;
@@@ -1966,8 -2033,8 +1965,8 @@@ static void fetch_symref(const char *pa
        struct active_request_slot *slot;
        struct slot_results results;
  
 -      url = xmalloc(strlen(remote->url) + strlen(path) + 1);
 -      sprintf(url, "%s%s", remote->url, path);
 +      url = xmalloc(strlen(repo->url) + strlen(path) + 1);
 +      sprintf(url, "%s%s", repo->url, path);
  
        slot = get_active_slot();
        slot->results = &results;
@@@ -2082,7 -2149,7 +2081,7 @@@ static int delete_remote_branch(char *p
                                     "of your current HEAD.\n"
                                     "If you are sure you want to delete it,"
                                     " run:\n\t'git http-push -D %s %s'",
 -                                   remote_ref->name, remote->url, pattern);
 +                                   remote_ref->name, repo->url, pattern);
                }
        }
  
        fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name);
        if (dry_run)
                return 0;
 -      url = xmalloc(strlen(remote->url) + strlen(remote_ref->name) + 1);
 -      sprintf(url, "%s%s", remote->url, remote_ref->name);
 +      url = xmalloc(strlen(repo->url) + strlen(remote_ref->name) + 1);
 +      sprintf(url, "%s%s", repo->url, remote_ref->name);
        slot = get_active_slot();
        slot->results = &results;
        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
@@@ -2127,15 -2194,14 +2126,15 @@@ int main(int argc, char **argv
        int rc = 0;
        int i;
        int new_refs;
 -      struct ref *ref;
 +      struct ref *ref, *local_refs;
 +      struct remote *remote;
        char *rewritten_url = NULL;
  
        git_extract_argv0_path(argv[0]);
  
        setup_git_directory();
  
 -      remote = xcalloc(sizeof(*remote), 1);
 +      repo = xcalloc(sizeof(*repo), 1);
  
        argv++;
        for (i = 1; i < argc; i++, argv++) {
                                continue;
                        }
                }
 -              if (!remote->url) {
 +              if (!repo->url) {
                        char *path = strstr(arg, "//");
 -                      remote->url = arg;
 -                      remote->path_len = strlen(arg);
 +                      repo->url = arg;
 +                      repo->path_len = strlen(arg);
                        if (path) {
 -                              remote->path = strchr(path+2, '/');
 -                              if (remote->path)
 -                                      remote->path_len = strlen(remote->path);
 +                              repo->path = strchr(path+2, '/');
 +                              if (repo->path)
 +                                      repo->path_len = strlen(repo->path);
                        }
                        continue;
                }
        die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI");
  #endif
  
 -      if (!remote->url)
 +      if (!repo->url)
                usage(http_push_usage);
  
        if (delete_branch && nr_refspec != 1)
  
        memset(remote_dir_exists, -1, 256);
  
 -      http_init(NULL);
 +      /*
 +       * Create a minimum remote by hand to give to http_init(),
 +       * primarily to allow it to look at the URL.
 +       */
 +      remote = xcalloc(sizeof(*remote), 1);
 +      ALLOC_GROW(remote->url, remote->url_nr + 1, remote->url_alloc);
 +      remote->url[remote->url_nr++] = repo->url;
 +      http_init(remote);
  
        no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
  
 -      if (remote->url && remote->url[strlen(remote->url)-1] != '/') {
 -              rewritten_url = xmalloc(strlen(remote->url)+2);
 -              strcpy(rewritten_url, remote->url);
 +      if (repo->url && repo->url[strlen(repo->url)-1] != '/') {
 +              rewritten_url = xmalloc(strlen(repo->url)+2);
 +              strcpy(rewritten_url, repo->url);
                strcat(rewritten_url, "/");
 -              remote->path = rewritten_url + (remote->path - remote->url);
 -              remote->path_len++;
 -              remote->url = rewritten_url;
 +              repo->path = rewritten_url + (repo->path - repo->url);
 +              repo->path_len++;
 +              repo->url = rewritten_url;
        }
  
        /* Verify DAV compliance/lock support */
        sigchain_push_common(remove_locks_on_signal);
  
        /* Check whether the remote has server info files */
 -      remote->can_update_info_refs = 0;
 -      remote->has_info_refs = remote_exists("info/refs");
 -      remote->has_info_packs = remote_exists("objects/info/packs");
 -      if (remote->has_info_refs) {
 +      repo->can_update_info_refs = 0;
 +      repo->has_info_refs = remote_exists("info/refs");
 +      repo->has_info_packs = remote_exists("objects/info/packs");
 +      if (repo->has_info_refs) {
                info_ref_lock = lock_remote("info/refs", LOCK_TIME);
                if (info_ref_lock)
 -                      remote->can_update_info_refs = 1;
 +                      repo->can_update_info_refs = 1;
                else {
 -                      fprintf(stderr, "Error: cannot lock existing info/refs\n");
 +                      error("cannot lock existing info/refs");
                        rc = 1;
                        goto cleanup;
                }
        }
 -      if (remote->has_info_packs)
 +      if (repo->has_info_packs)
                fetch_indices();
  
        /* Get a list of all local and remote heads to validate refspecs */
 -      get_local_heads();
 +      local_refs = get_local_heads();
        fprintf(stderr, "Fetching remote heads...\n");
        get_dav_remote_heads();
  
        }
  
        /* Update remote server info if appropriate */
 -      if (remote->has_info_refs && new_refs) {
 -              if (info_ref_lock && remote->can_update_info_refs) {
 +      if (repo->has_info_refs && new_refs) {
 +              if (info_ref_lock && repo->can_update_info_refs) {
                        fprintf(stderr, "Updating remote server info\n");
                        if (!dry_run)
                                update_remote_info_refs(info_ref_lock);
        free(rewritten_url);
        if (info_ref_lock)
                unlock_remote(info_ref_lock);
 -      free(remote);
 +      free(repo);
  
        curl_slist_free_all(no_pragma_header);
  
diff --combined index-pack.c
index 75468228d3933cc86c79f3595f7ff5e6b643cd7b,5dfe03ee6cbbf531a5db053fc8f8fd41b0a59aab..6e93ee6af64593937ee9b078e599e81d40b74303
@@@ -232,7 -232,7 +232,7 @@@ static void free_base_data(struct base_
  
  static void prune_base_data(struct base_data *retain)
  {
 -      struct base_data *b = base_cache;
 +      struct base_data *b;
        for (b = base_cache;
             base_cache_used > delta_base_cache_limit && b;
             b = b->child) {
@@@ -823,8 -823,7 +823,7 @@@ static void final(const char *final_pac
                }
                if (move_temp_to_file(curr_pack_name, final_pack_name))
                        die("cannot store pack file");
-       }
-       if (from_stdin)
+       } else if (from_stdin)
                chmod(final_pack_name, 0444);
  
        if (final_index_name != curr_index_name) {
                }
                if (move_temp_to_file(curr_index_name, final_index_name))
                        die("cannot store index file");
-       }
-       chmod(final_index_name, 0444);
+       } else
+               chmod(final_index_name, 0444);
  
        if (!from_stdin) {
                printf("%s\n", sha1_to_hex(sha1));
diff --combined sha1_file.c
index 37e833b77d1ee556d18256154073a706ab11b3a4,d978abf43d26a47c73f98c030802e4c7dffe049f..8fe135dc61908103cf2d7de700794843f83db057
@@@ -1919,7 -1919,25 +1919,7 @@@ off_t find_pack_entry_one(const unsigne
        return 0;
  }
  
 -int matches_pack_name(struct packed_git *p, const char *name)
 -{
 -      const char *last_c, *c;
 -
 -      if (!strcmp(p->pack_name, name))
 -              return 1;
 -
 -      for (c = p->pack_name, last_c = c; *c;)
 -              if (*c == '/')
 -                      last_c = ++c;
 -              else
 -                      ++c;
 -      if (!strcmp(last_c, name))
 -              return 1;
 -
 -      return 0;
 -}
 -
 -static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, const char **ignore_packed)
 +static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
  {
        static struct packed_git *last_found = (void *)1;
        struct packed_git *p;
        p = (last_found == (void *)1) ? packed_git : last_found;
  
        do {
 -              if (ignore_packed) {
 -                      const char **ig;
 -                      for (ig = ignore_packed; *ig; ig++)
 -                              if (matches_pack_name(p, *ig))
 -                                      break;
 -                      if (*ig)
 -                              goto next;
 -              }
 -
                if (p->num_bad_objects) {
                        unsigned i;
                        for (i = 0; i < p->num_bad_objects; i++)
@@@ -2011,7 -2038,7 +2011,7 @@@ int sha1_object_info(const unsigned cha
        struct pack_entry e;
        int status;
  
 -      if (!find_pack_entry(sha1, &e, NULL)) {
 +      if (!find_pack_entry(sha1, &e)) {
                /* Most likely it's a loose object. */
                status = sha1_loose_object_info(sha1, sizep);
                if (status >= 0)
  
                /* Not a loose object; someone else may have just packed it. */
                reprepare_packed_git();
 -              if (!find_pack_entry(sha1, &e, NULL))
 +              if (!find_pack_entry(sha1, &e))
                        return status;
        }
  
@@@ -2038,7 -2065,7 +2038,7 @@@ static void *read_packed_sha1(const uns
        struct pack_entry e;
        void *data;
  
 -      if (!find_pack_entry(sha1, &e, NULL))
 +      if (!find_pack_entry(sha1, &e))
                return NULL;
        data = cache_or_unpack_entry(e.p, e.offset, size, type, 1);
        if (!data) {
@@@ -2216,11 -2243,15 +2216,15 @@@ static void write_sha1_file_prepare(con
  }
  
  /*
-  * Move the just written object into its final resting place
+  * Move the just written object into its final resting place.
+  * NEEDSWORK: this should be renamed to finalize_temp_file() as
+  * "moving" is only a part of what it does, when no patch between
+  * master to pu changes the call sites of this function.
   */
  int move_temp_to_file(const char *tmpfile, const char *filename)
  {
        int ret = 0;
        if (link(tmpfile, filename))
                ret = errno;
  
         *
         * The same holds for FAT formatted media.
         *
-        * When this succeeds, we just return 0. We have nothing
+        * When this succeeds, we just return We have nothing
         * left to unlink.
         */
        if (ret && ret != EEXIST) {
                if (!rename(tmpfile, filename))
-                       return 0;
+                       goto out;
                ret = errno;
        }
        unlink(tmpfile);
                /* FIXME!!! Collision check here ? */
        }
  
+ out:
+       if (set_shared_perm(filename, (S_IFREG|0444)))
+               return error("unable to set permission to '%s'", filename);
        return 0;
  }
  
@@@ -2272,7 -2306,6 +2279,6 @@@ static void close_sha1_file(int fd
  {
        if (fsync_object_files)
                fsync_or_die(fd, "sha1 file");
-       fchmod(fd, 0444);
        if (close(fd) != 0)
                die("error when closing sha1 file (%s)", strerror(errno));
  }
@@@ -2437,17 -2470,17 +2443,17 @@@ int has_pack_file(const unsigned char *
        return 1;
  }
  
 -int has_sha1_pack(const unsigned char *sha1, const char **ignore_packed)
 +int has_sha1_pack(const unsigned char *sha1)
  {
        struct pack_entry e;
 -      return find_pack_entry(sha1, &e, ignore_packed);
 +      return find_pack_entry(sha1, &e);
  }
  
  int has_sha1_file(const unsigned char *sha1)
  {
        struct pack_entry e;
  
 -      if (find_pack_entry(sha1, &e, NULL))
 +      if (find_pack_entry(sha1, &e))
                return 1;
        return has_loose_object(sha1);
  }
diff --combined t/t1301-shared-repo.sh
index dc4485409dd5e5f28d07c71c2decce1f35237bf4,3c8a2373ac0bf8e6e9737df3fec3b7d66d044a18..750fbb32e87e0eb8f7a95928f9b407036822c7ad
@@@ -26,7 -26,7 +26,7 @@@ modebits () 
  
  for u in 002 022
  do
 -      test_expect_success "shared=1 does not clear bits preset by umask $u" '
 +      test_expect_success POSIXPERM "shared=1 does not clear bits preset by umask $u" '
                mkdir sub && (
                        cd sub &&
                        umask $u &&
@@@ -54,7 -54,7 +54,7 @@@ test_expect_success 'shared=all' 
        test 2 = $(git config core.sharedrepository)
  '
  
 -test_expect_success 'update-server-info honors core.sharedRepository' '
 +test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' '
        : > a1 &&
        git add a1 &&
        test_tick &&
@@@ -85,7 -85,7 +85,7 @@@ d
        git config core.sharedrepository "$u" &&
        umask 0277 &&
  
 -      test_expect_success "shared = $u ($y) ro" '
 +      test_expect_success POSIXPERM "shared = $u ($y) ro" '
  
                rm -f .git/info/refs &&
                git update-server-info &&
@@@ -97,7 -97,7 +97,7 @@@
        '
  
        umask 077 &&
 -      test_expect_success "shared = $u ($x) rw" '
 +      test_expect_success POSIXPERM "shared = $u ($x) rw" '
  
                rm -f .git/info/refs &&
                git update-server-info &&
  
  done
  
 -test_expect_success 'git reflog expire honors core.sharedRepository' '
 +test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' '
        git config core.sharedRepository group &&
        git reflog expire --all &&
        actual="$(ls -l .git/logs/refs/heads/master)" &&
        esac
  '
  
+ test_expect_success 'forced modes' '
+       mkdir -p templates/hooks &&
+       echo update-server-info >templates/hooks/post-update &&
+       chmod +x templates/hooks/post-update &&
+       echo : >random-file &&
+       mkdir new &&
+       (
+               cd new &&
+               umask 002 &&
+               git init --shared=0660 --template=../templates &&
+               >frotz &&
+               git add frotz &&
+               git commit -a -m initial &&
+               git repack
+       ) &&
+       find new/.git -print |
+       xargs ls -ld >actual &&
+       # Everything must be unaccessible to others
+       test -z "$(sed -n -e "/^.......---/d" actual)" &&
+       # All directories must have either 2770 or 770
+       test -z "$(sed -n -e "/^drwxrw[sx]---/d" -e "/^d/p" actual)" &&
+       # post-update hook must be 0770
+       test -z "$(sed -n -e "/post-update/{
+               /^-rwxrwx---/d
+               p
+       }" actual)" &&
+       # All files inside objects must be 0440
+       test -z "$(sed -n -e "/objects\//{
+               /^d/d
+               /^-r--r-----/d
+       }" actual)"
+ '
  test_done