Merge branch 'jk/prune-mtime' into maint
authorJunio C Hamano <gitster@pobox.com>
Thu, 5 Mar 2015 21:13:08 +0000 (13:13 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 5 Mar 2015 21:13:08 +0000 (13:13 -0800)
In v2.2.0, we broke "git prune" that runs in a repository that
borrows from an alternate object store.

* jk/prune-mtime:
sha1_file: fix iterating loose alternate objects
for_each_loose_file_in_objdir: take an optional strbuf path

1  2 
cache.h
sha1_file.c
diff --combined cache.h
index 04951ddcbf7cf2cb61957568f8608b0fbbd9c9da,4743f7ed9fbbfcd14c81ca7ea12aa4c1fcc1fe19..4d02efc905456e61ce841ec1db2cc19491346257
+++ b/cache.h
@@@ -65,6 -65,13 +65,6 @@@ unsigned long git_deflate_bound(git_zst
   *
   * The value 0160000 is not normally a valid mode, and
   * also just happens to be S_IFDIR + S_IFLNK
 - *
 - * NOTE! We *really* shouldn't depend on the S_IFxxx macros
 - * always having the same values everywhere. We should use
 - * our internal git values for these things, and then we can
 - * translate that to the OS-specific value. It just so
 - * happens that everybody shares the same bit representation
 - * in the UNIX world (and apparently wider too..)
   */
  #define S_IFGITLINK   0160000
  #define S_ISGITLINK(m)        (((m) & S_IFMT) == S_IFGITLINK)
@@@ -563,11 -570,29 +563,11 @@@ extern void fill_stat_cache_info(struc
  #define REFRESH_IN_PORCELAIN  0x0020  /* user friendly output, not "needs update" */
  extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
  
 -struct lock_file {
 -      struct lock_file *next;
 -      int fd;
 -      pid_t owner;
 -      char on_list;
 -      char filename[PATH_MAX];
 -};
 -#define LOCK_DIE_ON_ERROR 1
 -#define LOCK_NODEREF 2
 -extern int unable_to_lock_error(const char *path, int err);
 -extern void unable_to_lock_message(const char *path, int err,
 -                                 struct strbuf *buf);
 -extern NORETURN void unable_to_lock_index_die(const char *path, int err);
 -extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
 -extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
 -extern int commit_lock_file(struct lock_file *);
 -extern int reopen_lock_file(struct lock_file *);
  extern void update_index_if_able(struct index_state *, struct lock_file *);
  
  extern int hold_locked_index(struct lock_file *, int);
  extern void set_alternate_index_output(const char *);
 -extern int close_lock_file(struct lock_file *);
 -extern void rollback_lock_file(struct lock_file *);
 +
  extern int delete_ref(const char *, const unsigned char *sha1, int delopt);
  
  /* Environment bits from configuration mechanism */
@@@ -610,8 -635,6 +610,8 @@@ extern int fsync_object_files
  extern int core_preload_index;
  extern int core_apply_sparse_checkout;
  extern int precomposed_unicode;
 +extern int protect_hfs;
 +extern int protect_ntfs;
  
  /*
   * The character that begins a commented line in user-editable file
@@@ -826,7 -849,6 +826,7 @@@ int normalize_path_copy(char *dst, cons
  int longest_ancestor_length(const char *path, struct string_list *prefixes);
  char *strip_path_suffix(const char *path, const char *suffix);
  int daemon_avoid_alias(const char *path);
 +extern int is_ntfs_dotgit(const char *name);
  
  /* object replacement */
  #define LOOKUP_REPLACE_OBJECT 1
@@@ -946,8 -968,8 +946,8 @@@ extern int for_each_abbrev(const char *
  extern int get_sha1_hex(const char *hex, unsigned char *sha1);
  
  extern char *sha1_to_hex(const unsigned char *sha1);  /* static buffer result! */
 -extern int read_ref_full(const char *refname, unsigned char *sha1,
 -                       int reading, int *flags);
 +extern int read_ref_full(const char *refname, int resolve_flags,
 +                       unsigned char *sha1, int *flags);
  extern int read_ref(const char *refname, unsigned char *sha1);
  
  /*
   * or the input ref.
   *
   * If the reference cannot be resolved to an object, the behavior
 - * depends on the "reading" argument:
 + * depends on the RESOLVE_REF_READING flag:
   *
 - * - If reading is set, return NULL.
 + * - If RESOLVE_REF_READING is set, return NULL.
   *
 - * - If reading is not set, clear sha1 and return the name of the last
 - *   reference name in the chain, which will either be a non-symbolic
 + * - If RESOLVE_REF_READING is not set, clear sha1 and return the name of
 + *   the last reference name in the chain, which will either be a non-symbolic
   *   reference or an undefined reference.  If this is a prelude to
   *   "writing" to the ref, the return value is the name of the ref
   *   that will actually be created or changed.
   *
 - * If flag is non-NULL, set the value that it points to the
 + * If the RESOLVE_REF_NO_RECURSE flag is passed, only resolves one
 + * level of symbolic reference.  The value stored in sha1 for a symbolic
 + * reference will always be null_sha1 in this case, and the return
 + * value is the reference that the symref refers to directly.
 + *
 + * If flags is non-NULL, set the value that it points to the
   * combination of REF_ISPACKED (if the reference was found among the
 - * packed references) and REF_ISSYMREF (if the initial reference was a
 - * symbolic reference).
 + * packed references), REF_ISSYMREF (if the initial reference was a
 + * symbolic reference), REF_BAD_NAME (if the reference name is ill
 + * formed --- see RESOLVE_REF_ALLOW_BAD_NAME below), and REF_ISBROKEN
 + * (if the ref is malformed or has a bad name). See refs.h for more detail
 + * on each flag.
   *
   * If ref is not a properly-formatted, normalized reference, return
   * NULL.  If more than MAXDEPTH recursive symbolic lookups are needed,
   * give up and return NULL.
   *
 - * errno is set to something meaningful on error.
 + * RESOLVE_REF_ALLOW_BAD_NAME allows resolving refs even when their
 + * name is invalid according to git-check-ref-format(1).  If the name
 + * is bad then the value stored in sha1 will be null_sha1 and the two
 + * flags REF_ISBROKEN and REF_BAD_NAME will be set.
 + *
 + * Even with RESOLVE_REF_ALLOW_BAD_NAME, names that escape the refs/
 + * directory and do not consist of all caps and underscores cannot be
 + * resolved. The function returns NULL for such ref names.
 + * Caps and underscores refers to the special refs, such as HEAD,
 + * FETCH_HEAD and friends, that all live outside of the refs/ directory.
   */
 -extern const char *resolve_ref_unsafe(const char *ref, unsigned char *sha1, int reading, int *flag);
 -extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, int *flag);
 +#define RESOLVE_REF_READING 0x01
 +#define RESOLVE_REF_NO_RECURSE 0x02
 +#define RESOLVE_REF_ALLOW_BAD_NAME 0x04
 +extern const char *resolve_ref_unsafe(const char *ref, int resolve_flags, unsigned char *sha1, int *flags);
 +extern char *resolve_refdup(const char *ref, int resolve_flags, unsigned char *sha1, int *flags);
  
  extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
  extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
@@@ -1254,6 -1256,10 +1254,10 @@@ extern int unpack_object_header(struct 
   *
   * Any callback that is NULL will be ignored. Callbacks returning non-zero
   * will end the iteration.
+  *
+  * In the "buf" variant, "path" is a strbuf which will also be used as a
+  * scratch buffer, but restored to its original contents before
+  * the function returns.
   */
  typedef int each_loose_object_fn(const unsigned char *sha1,
                                 const char *path,
@@@ -1269,6 -1275,11 +1273,11 @@@ int for_each_loose_file_in_objdir(cons
                                  each_loose_cruft_fn cruft_cb,
                                  each_loose_subdir_fn subdir_cb,
                                  void *data);
+ int for_each_loose_file_in_objdir_buf(struct strbuf *path,
+                                     each_loose_object_fn obj_cb,
+                                     each_loose_cruft_fn cruft_cb,
+                                     each_loose_subdir_fn subdir_cb,
+                                     void *data);
  
  /*
   * Iterate over loose and packed objects in both the local
@@@ -1498,7 -1509,7 +1507,7 @@@ extern const char *pager_program
  extern int pager_in_use(void);
  extern int pager_use_color;
  extern int term_columns(void);
 -extern int decimal_width(int);
 +extern int decimal_width(uintmax_t);
  extern int check_pager_config(const char *cmd);
  
  extern const char *editor_program;
diff --combined sha1_file.c
index 30995e61b38fbfd1733acc5c3c5866b61d9f09e1,a41cc4f65fe139cede1cc8ebd26efc024dec8e26..69a60ec88bad190f885cd89a93573236a88ddbd9
@@@ -8,7 -8,6 +8,7 @@@
   */
  #include "cache.h"
  #include "string-list.h"
 +#include "lockfile.h"
  #include "delta.h"
  #include "pack.h"
  #include "blob.h"
@@@ -1198,7 -1197,7 +1198,7 @@@ static void report_pack_garbage(struct 
        if (!report_garbage)
                return;
  
 -      sort_string_list(list);
 +      string_list_sort(list);
  
        for (i = 0; i < list->nr; i++) {
                const char *path = list->items[i].string;
@@@ -3359,31 -3358,42 +3359,42 @@@ static int for_each_file_in_obj_subdir(
        return r;
  }
  
- int for_each_loose_file_in_objdir(const char *path,
+ int for_each_loose_file_in_objdir_buf(struct strbuf *path,
                            each_loose_object_fn obj_cb,
                            each_loose_cruft_fn cruft_cb,
                            each_loose_subdir_fn subdir_cb,
                            void *data)
  {
-       struct strbuf buf = STRBUF_INIT;
-       size_t baselen;
+       size_t baselen = path->len;
        int r = 0;
        int i;
  
-       strbuf_addstr(&buf, path);
-       strbuf_addch(&buf, '/');
-       baselen = buf.len;
        for (i = 0; i < 256; i++) {
-               strbuf_addf(&buf, "%02x", i);
-               r = for_each_file_in_obj_subdir(i, &buf, obj_cb, cruft_cb,
+               strbuf_addf(path, "/%02x", i);
+               r = for_each_file_in_obj_subdir(i, path, obj_cb, cruft_cb,
                                                subdir_cb, data);
-               strbuf_setlen(&buf, baselen);
+               strbuf_setlen(path, baselen);
                if (r)
                        break;
        }
  
+       return r;
+ }
+ int for_each_loose_file_in_objdir(const char *path,
+                                 each_loose_object_fn obj_cb,
+                                 each_loose_cruft_fn cruft_cb,
+                                 each_loose_subdir_fn subdir_cb,
+                                 void *data)
+ {
+       struct strbuf buf = STRBUF_INIT;
+       int r;
+       strbuf_addstr(&buf, path);
+       r = for_each_loose_file_in_objdir_buf(&buf, obj_cb, cruft_cb,
+                                             subdir_cb, data);
        strbuf_release(&buf);
        return r;
  }
  
@@@ -3396,9 -3406,16 +3407,16 @@@ static int loose_from_alt_odb(struct al
                              void *vdata)
  {
        struct loose_alt_odb_data *data = vdata;
-       return for_each_loose_file_in_objdir(alt->base,
-                                            data->cb, NULL, NULL,
-                                            data->data);
+       struct strbuf buf = STRBUF_INIT;
+       int r;
+       /* copy base not including trailing '/' */
+       strbuf_add(&buf, alt->base, alt->name - alt->base - 1);
+       r = for_each_loose_file_in_objdir_buf(&buf,
+                                             data->cb, NULL, NULL,
+                                             data->data);
+       strbuf_release(&buf);
+       return r;
  }
  
  int for_each_loose_object(each_loose_object_fn cb, void *data)