Merge branch 'js/maint-1.6.0-path-normalize' into maint-1.6.1
authorJunio C Hamano <gitster@pobox.com>
Sun, 22 Mar 2009 05:59:19 +0000 (22:59 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 22 Mar 2009 05:59:19 +0000 (22:59 -0700)
* js/maint-1.6.0-path-normalize:
Remove unused normalize_absolute_path()
Test and fix normalize_path_copy()
Fix GIT_CEILING_DIRECTORIES on Windows
Move sanitary_path_copy() to path.c and rename it to normalize_path_copy()
Make test-path-utils more robust against incorrect use

1  2 
cache.h
setup.c
diff --combined cache.h
index 0e2f219b2b4d9ff5944e68dbaf2338c76055161f,39f0d6fea4b04c6c7477c6e874b69f92b11e751c..15675701fd64d53cff9c27505cac6f4f14b1341d
+++ b/cache.h
@@@ -6,22 -6,12 +6,22 @@@
  #include "hash.h"
  
  #include SHA1_HEADER
 -#include <zlib.h>
 +#ifndef git_SHA_CTX
 +#define git_SHA_CTX   SHA_CTX
 +#define git_SHA1_Init SHA1_Init
 +#define git_SHA1_Update       SHA1_Update
 +#define git_SHA1_Final        SHA1_Final
 +#endif
  
 +#include <zlib.h>
  #if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200
  #define deflateBound(c,s)  ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
  #endif
  
 +void git_inflate_init(z_streamp strm);
 +void git_inflate_end(z_streamp strm);
 +int git_inflate(z_streamp strm, int flush);
 +
  #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
  #define DTYPE(de)     ((de)->d_type)
  #else
@@@ -119,26 -109,6 +119,26 @@@ struct ondisk_cache_entry 
        char name[FLEX_ARRAY]; /* more */
  };
  
 +/*
 + * This struct is used when CE_EXTENDED bit is 1
 + * The struct must match ondisk_cache_entry exactly from
 + * ctime till flags
 + */
 +struct ondisk_cache_entry_extended {
 +      struct cache_time ctime;
 +      struct cache_time mtime;
 +      unsigned int dev;
 +      unsigned int ino;
 +      unsigned int mode;
 +      unsigned int uid;
 +      unsigned int gid;
 +      unsigned int size;
 +      unsigned char sha1[20];
 +      unsigned short flags;
 +      unsigned short flags2;
 +      char name[FLEX_ARRAY]; /* more */
 +};
 +
  struct cache_entry {
        unsigned int ce_ctime;
        unsigned int ce_mtime;
  
  #define CE_NAMEMASK  (0x0fff)
  #define CE_STAGEMASK (0x3000)
 +#define CE_EXTENDED  (0x4000)
  #define CE_VALID     (0x8000)
  #define CE_STAGESHIFT 12
  
 -/* In-memory only */
 +/*
 + * Range 0xFFFF0000 in ce_flags is divided into
 + * two parts: in-memory flags and on-disk ones.
 + * Flags in CE_EXTENDED_FLAGS will get saved on-disk
 + * if you want to save a new flag, add it in
 + * CE_EXTENDED_FLAGS
 + *
 + * In-memory only flags
 + */
  #define CE_UPDATE    (0x10000)
  #define CE_REMOVE    (0x20000)
  #define CE_UPTODATE  (0x40000)
  #define CE_HASHED    (0x100000)
  #define CE_UNHASHED  (0x200000)
  
 +/*
 + * Extended on-disk flags
 + */
 +#define CE_INTENT_TO_ADD 0x20000000
 +/* CE_EXTENDED2 is for future extension */
 +#define CE_EXTENDED2 0x80000000
 +
 +#define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD)
 +
 +/*
 + * Safeguard to avoid saving wrong flags:
 + *  - CE_EXTENDED2 won't get saved until its semantic is known
 + *  - Bits in 0x0000FFFF have been saved in ce_flags already
 + *  - Bits in 0x003F0000 are currently in-memory flags
 + */
 +#if CE_EXTENDED_FLAGS & 0x803FFFFF
 +#error "CE_EXTENDED_FLAGS out of range"
 +#endif
 +
  /*
   * Copy the sha1 and stat state of a cache entry from one to
   * another. But we never change the name, or the hash state!
@@@ -228,9 -170,7 +228,9 @@@ static inline size_t ce_namelen(const s
  }
  
  #define ce_size(ce) cache_entry_size(ce_namelen(ce))
 -#define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce))
 +#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \
 +                          ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
 +                          ondisk_cache_entry_size(ce_namelen(ce)))
  #define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT)
  #define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
  #define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
@@@ -273,10 -213,8 +273,10 @@@ static inline int ce_to_dtype(const str
        (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
        S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK)
  
 -#define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)
 -#define ondisk_cache_entry_size(len) ((offsetof(struct ondisk_cache_entry,name) + (len) + 8) & ~7)
 +#define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
 +#define cache_entry_size(len) flexible_size(cache_entry,len)
 +#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len)
 +#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len)
  
  struct index_state {
        struct cache_entry **cache;
@@@ -317,7 -255,6 +317,7 @@@ static inline void remove_name_hash(str
  
  #define read_cache() read_index(&the_index)
  #define read_cache_from(path) read_index_from(&the_index, (path))
 +#define read_cache_preload(pathspec) read_index_preload(&the_index, (pathspec))
  #define is_cache_unborn() is_index_unborn(&the_index)
  #define read_cache_unmerged() read_index_unmerged(&the_index)
  #define write_cache(newfd, cache, entries) write_index(&the_index, (newfd))
@@@ -377,7 -314,6 +377,7 @@@ extern int is_bare_repository(void)
  extern int is_inside_git_dir(void);
  extern char *git_work_tree_cfg;
  extern int is_inside_work_tree(void);
 +extern int have_git_dir(void);
  extern const char *get_git_dir(void);
  extern char *get_object_directory(void);
  extern char *get_index_file(void);
@@@ -424,7 -360,6 +424,7 @@@ extern int init_db(const char *template
  
  /* Initialize and use the cache information */
  extern int read_index(struct index_state *);
 +extern int read_index_preload(struct index_state *, const char **pathspec);
  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 *);
@@@ -438,7 -373,6 +438,7 @@@ extern int index_name_pos(const struct 
  #define ADD_CACHE_OK_TO_REPLACE 2     /* Ok to replace file/directory */
  #define ADD_CACHE_SKIP_DFCHECK 4      /* Ok to skip DF conflict checks */
  #define ADD_CACHE_JUST_APPEND 8               /* Append only; tree.c::read_tree() */
 +#define ADD_CACHE_NEW_ONLY 16         /* Do not replace existing ones */
  extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
  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);
@@@ -447,8 -381,6 +447,8 @@@ extern int remove_file_from_index(struc
  #define ADD_CACHE_VERBOSE 1
  #define ADD_CACHE_PRETEND 2
  #define ADD_CACHE_IGNORE_ERRORS       4
 +#define ADD_CACHE_IGNORE_REMOVAL 8
 +#define ADD_CACHE_INTENT 16
  extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
  extern int add_file_to_index(struct index_state *, const char *path, int flags);
  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
@@@ -464,6 -396,7 +464,6 @@@ extern int ie_modified(const struct ind
  
  extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
  extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
 -extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
  extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
  extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
  
@@@ -484,7 -417,6 +484,7 @@@ struct lock_file 
  };
  #define LOCK_DIE_ON_ERROR 1
  #define LOCK_NODEREF 2
 +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 *);
@@@ -516,7 -448,6 +516,7 @@@ extern size_t packed_git_limit
  extern size_t delta_base_cache_limit;
  extern int auto_crlf;
  extern int fsync_object_files;
 +extern int core_preload_index;
  
  enum safe_crlf {
        SAFE_CRLF_FALSE = 0,
  extern enum safe_crlf safe_crlf;
  
  enum branch_track {
 +      BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
        BRANCH_TRACK_REMOTE,
        BRANCH_TRACK_ALWAYS,
@@@ -587,13 -517,6 +587,13 @@@ static inline void hashclr(unsigned cha
  {
        memset(hash, 0, 20);
  }
 +extern int is_empty_blob_sha1(const unsigned char *sha1);
 +
 +#define EMPTY_TREE_SHA1_HEX \
 +      "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
 +#define EMPTY_TREE_SHA1_BIN \
 +       "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
 +       "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
  
  int git_mkstemp(char *path, size_t n, const char *template);
  
@@@ -621,11 -544,10 +621,11 @@@ static inline int is_absolute_path(cons
  {
        return path[0] == '/' || has_dos_drive_prefix(path);
  }
 +int is_directory(const char *);
  const char *make_absolute_path(const char *path);
  const char *make_nonrelative_path(const char *path);
  const char *make_relative_path(const char *abs, const char *base);
- int normalize_absolute_path(char *buf, const char *path);
+ int normalize_path_copy(char *dst, const char *src);
  int longest_ancestor_length(const char *path, const char *prefix_list);
  
  /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
@@@ -639,9 -561,6 +639,9 @@@ extern int force_object_loose(const uns
  /* just like read_sha1_file(), but non fatal in presence of bad objects */
  extern void *read_object(const unsigned char *sha1, enum object_type *type, unsigned long *size);
  
 +/* global flag to enable extra checks when accessing packed objects */
 +extern int do_check_packed_object_crc;
 +
  extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
  
  extern int move_temp_to_file(const char *tmpfile, const char *filename);
@@@ -733,8 -652,6 +733,8 @@@ extern struct alternate_object_databas
  } *alt_odb_list;
  extern void prepare_alt_odb(void);
  extern void add_to_alternates_file(const char *reference);
 +typedef int alt_odb_fn(struct alternate_object_database *, void *);
 +extern void foreach_alt_odb(alt_odb_fn, void*);
  
  struct pack_window {
        struct pack_window *next;
@@@ -804,11 -721,7 +804,11 @@@ extern struct child_process *git_connec
  extern int finish_connect(struct child_process *conn);
  extern int path_match(const char *path, int nr, char **match);
  extern int get_ack(int fd, unsigned char *result_sha1);
 -extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags);
 +struct extra_have_objects {
 +      int nr, alloc;
 +      unsigned char (*array)[20];
 +};
 +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);
@@@ -826,13 -739,12 +826,13 @@@ extern unsigned char* use_pack(struct p
  extern void close_pack_windows(struct packed_git *);
  extern void unuse_pack(struct pack_window **);
  extern void free_pack_by_name(const char *);
 +extern void clear_delta_base_cache(void);
  extern struct packed_git *add_packed_git(const char *, int, int);
  extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
  extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
  extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
  extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
 -extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
 +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);
@@@ -844,6 -756,7 +844,6 @@@ typedef int (*config_fn_t)(const char *
  extern int git_default_config(const char *, const char *, void *);
  extern int git_config_from_file(config_fn_t fn, const char *, void *);
  extern int git_config(config_fn_t fn, void *);
 -extern int git_parse_long(const char *, long *);
  extern int git_parse_ulong(const char *, unsigned long *);
  extern int git_config_int(const char *, const char *);
  extern unsigned long git_config_ulong(const char *, const char *);
diff --combined setup.c
index dfda532adc16f5e6d25d7cfc5add3e0e2b6a5209,59735c14506fbf29549628294f98a7d0c7b64b79..6c2deda18492acb5a8597563d6843f9d0dd232c0
+++ b/setup.c
@@@ -4,92 -4,6 +4,6 @@@
  static int inside_git_dir = -1;
  static int inside_work_tree = -1;
  
- static int sanitary_path_copy(char *dst, const char *src)
- {
-       char *dst0;
-       if (has_dos_drive_prefix(src)) {
-               *dst++ = *src++;
-               *dst++ = *src++;
-       }
-       dst0 = dst;
-       if (is_dir_sep(*src)) {
-               *dst++ = '/';
-               while (is_dir_sep(*src))
-                       src++;
-       }
-       for (;;) {
-               char c = *src;
-               /*
-                * A path component that begins with . could be
-                * special:
-                * (1) "." and ends   -- ignore and terminate.
-                * (2) "./"           -- ignore them, eat slash and continue.
-                * (3) ".." and ends  -- strip one and terminate.
-                * (4) "../"          -- strip one, eat slash and continue.
-                */
-               if (c == '.') {
-                       if (!src[1]) {
-                               /* (1) */
-                               src++;
-                       } else if (is_dir_sep(src[1])) {
-                               /* (2) */
-                               src += 2;
-                               while (is_dir_sep(*src))
-                                       src++;
-                               continue;
-                       } else if (src[1] == '.') {
-                               if (!src[2]) {
-                                       /* (3) */
-                                       src += 2;
-                                       goto up_one;
-                               } else if (is_dir_sep(src[2])) {
-                                       /* (4) */
-                                       src += 3;
-                                       while (is_dir_sep(*src))
-                                               src++;
-                                       goto up_one;
-                               }
-                       }
-               }
-               /* copy up to the next '/', and eat all '/' */
-               while ((c = *src++) != '\0' && !is_dir_sep(c))
-                       *dst++ = c;
-               if (is_dir_sep(c)) {
-                       *dst++ = '/';
-                       while (is_dir_sep(c))
-                               c = *src++;
-                       src--;
-               } else if (!c)
-                       break;
-               continue;
-       up_one:
-               /*
-                * dst0..dst is prefix portion, and dst[-1] is '/';
-                * go up one level.
-                */
-               dst -= 2; /* go past trailing '/' if any */
-               if (dst < dst0)
-                       return -1;
-               while (1) {
-                       if (dst <= dst0)
-                               break;
-                       c = *dst--;
-                       if (c == '/') { /* MinGW: cannot be '\\' anymore */
-                               dst += 2;
-                               break;
-                       }
-               }
-       }
-       *dst = '\0';
-       return 0;
- }
  const char *prefix_path(const char *prefix, int len, const char *path)
  {
        const char *orig = path;
                        memcpy(sanitized, prefix, len);
                strcpy(sanitized + len, path);
        }
-       if (sanitary_path_copy(sanitized, sanitized))
+       if (normalize_path_copy(sanitized, sanitized))
                goto error_out;
        if (is_absolute_path(orig)) {
                const char *work_tree = get_git_work_tree();
@@@ -456,11 -370,7 +370,11 @@@ const char *setup_git_directory_gently(
                        inside_git_dir = 1;
                        if (!work_tree_env)
                                inside_work_tree = 0;
 -                      setenv(GIT_DIR_ENVIRONMENT, ".", 1);
 +                      if (offset != len) {
 +                              cwd[offset] = '\0';
 +                              setenv(GIT_DIR_ENVIRONMENT, cwd, 1);
 +                      } else
 +                              setenv(GIT_DIR_ENVIRONMENT, ".", 1);
                        check_repository_format_gently(nongit_ok);
                        return NULL;
                }
                                *nongit_ok = 1;
                                return NULL;
                        }
 -                      die("Not a git repository");
 +                      die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
                }
 -              chdir("..");
 +              if (chdir(".."))
 +                      die("Cannot change to %s/..: %s", cwd, strerror(errno));
        }
  
        inside_git_dir = 0;