Merge branch 'jn/thinner-wrapper'
authorJunio C Hamano <gitster@pobox.com>
Sat, 4 Dec 2010 00:13:06 +0000 (16:13 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 4 Dec 2010 00:13:06 +0000 (16:13 -0800)
* jn/thinner-wrapper:
Remove pack file handling dependency from wrapper.o
pack-objects: mark file-local variable static
wrapper: give zlib wrappers their own translation unit
strbuf: move strbuf_branchname to sha1_name.c
path helpers: move git_mkstemp* to wrapper.c
wrapper: move odb_* to environment.c
wrapper: move xmmap() to sha1_file.c

1  2 
Makefile
builtin/pack-objects.c
environment.c
git-compat-util.h
sha1_file.c
sha1_name.c
diff --combined Makefile
index 29ebe70599aa9c01ddb84e5611ac08d441adef4c,a8ba33635db62b95a948fbe9ce00feb9c59efc43..7a5fb699d193d95c763cc310d8b6b944d1aa4119
+++ b/Makefile
@@@ -70,11 -70,6 +70,11 @@@ all:
  #
  # Define NO_STRTOK_R if you don't have strtok_r in the C library.
  #
 +# Define NO_FNMATCH if you don't have fnmatch in the C library.
 +#
 +# Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
 +# FNM_CASEFOLD GNU extension.
 +#
  # Define NO_LIBGEN_H if you don't have libgen.h.
  #
  # Define NEEDS_LIBGEN if your libgen needs -lgen when linking
@@@ -406,7 -401,6 +406,7 @@@ EXTRA_PROGRAMS 
  # ... and all the rest that could be moved out of bindir to gitexecdir
  PROGRAMS += $(EXTRA_PROGRAMS)
  
 +PROGRAM_OBJS += daemon.o
  PROGRAM_OBJS += fast-import.o
  PROGRAM_OBJS += imap-send.o
  PROGRAM_OBJS += shell.o
@@@ -502,8 -496,6 +502,8 @@@ LIB_H += compat/bswap.
  LIB_H += compat/cygwin.h
  LIB_H += compat/mingw.h
  LIB_H += compat/win32/pthread.h
 +LIB_H += compat/win32/syslog.h
 +LIB_H += compat/win32/sys/poll.h
  LIB_H += csum-file.h
  LIB_H += decorate.h
  LIB_H += delta.h
@@@ -670,6 -662,7 +670,7 @@@ LIB_OBJS += write_or_die.
  LIB_OBJS += ws.o
  LIB_OBJS += wt-status.o
  LIB_OBJS += xdiff-interface.o
+ LIB_OBJS += zlib.o
  
  BUILTIN_OBJS += builtin/add.o
  BUILTIN_OBJS += builtin/annotate.o
@@@ -854,7 -847,6 +855,7 @@@ ifeq ($(uname_S),SunOS
        NO_MKDTEMP = YesPlease
        NO_MKSTEMPS = YesPlease
        NO_REGEX = YesPlease
 +      NO_FNMATCH_CASEFOLD = YesPlease
        ifeq ($(uname_R),5.6)
                SOCKLEN_T = int
                NO_HSTRERROR = YesPlease
@@@ -1061,7 -1053,6 +1062,7 @@@ ifeq ($(uname_S),Windows
        NO_STRCASESTR = YesPlease
        NO_STRLCPY = YesPlease
        NO_STRTOK_R = YesPlease
 +      NO_FNMATCH = YesPlease
        NO_MEMMEM = YesPlease
        # NEEDS_LIBICONV = YesPlease
        NO_ICONV = YesPlease
        NO_SVN_TESTS = YesPlease
        NO_PERL_MAKEMAKER = YesPlease
        RUNTIME_PREFIX = YesPlease
 -      NO_POSIX_ONLY_PROGRAMS = YesPlease
        NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
        NO_NSEC = YesPlease
        USE_WIN32_MMAP = YesPlease
        NO_CURL = YesPlease
        NO_PYTHON = YesPlease
        BLK_SHA1 = YesPlease
 +      NO_POSIX_GOODIES = UnfortunatelyYes
        NATIVE_CRLF = YesPlease
  
        CC = compat/vcbuild/scripts/clink.pl
        AR = compat/vcbuild/scripts/lib.pl
        CFLAGS =
        BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
 -      COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o
 -      COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
 +      COMPAT_OBJS = compat/msvc.o compat/winansi.o compat/win32/pthread.o compat/win32/syslog.o compat/win32/sys/poll.o
 +      COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
        BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
        EXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib
        PTHREAD_LIBS =
  endif
        X = .exe
  endif
 +ifeq ($(uname_S),Interix)
 +      NO_SYS_POLL_H = YesPlease
 +      NO_INTTYPES_H = YesPlease
 +      NO_INITGROUPS = YesPlease
 +      NO_IPV6 = YesPlease
 +      NO_MEMMEM = YesPlease
 +      NO_MKDTEMP = YesPlease
 +      NO_STRTOUMAX = YesPlease
 +      NO_NSEC = YesPlease
 +      NO_MKSTEMPS = YesPlease
 +      ifeq ($(uname_R),3.5)
 +              NO_INET_NTOP = YesPlease
 +              NO_INET_PTON = YesPlease
 +      endif
 +      ifeq ($(uname_R),5.2)
 +              NO_INET_NTOP = YesPlease
 +              NO_INET_PTON = YesPlease
 +      endif
 +endif
  ifneq (,$(findstring MINGW,$(uname_S)))
        pathsep = ;
        NO_PREAD = YesPlease
        NO_STRCASESTR = YesPlease
        NO_STRLCPY = YesPlease
        NO_STRTOK_R = YesPlease
 +      NO_FNMATCH = YesPlease
        NO_MEMMEM = YesPlease
        NEEDS_LIBICONV = YesPlease
        OLD_ICONV = YesPlease
        NO_SVN_TESTS = YesPlease
        NO_PERL_MAKEMAKER = YesPlease
        RUNTIME_PREFIX = YesPlease
 -      NO_POSIX_ONLY_PROGRAMS = YesPlease
        NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
        NO_NSEC = YesPlease
        USE_WIN32_MMAP = YesPlease
        NO_PYTHON = YesPlease
        BLK_SHA1 = YesPlease
        ETAGS_TARGET = ETAGS
 -      COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32
 +      NO_INET_PTON = YesPlease
 +      NO_INET_NTOP = YesPlease
 +      NO_POSIX_GOODIES = UnfortunatelyYes
 +      COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 -      COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \
 -              compat/win32/pthread.o
 +      COMPAT_OBJS += compat/mingw.o compat/winansi.o \
 +              compat/win32/pthread.o compat/win32/syslog.o \
 +              compat/win32/sys/poll.o
        EXTLIBS += -lws2_32
        PTHREAD_LIBS =
        X = .exe
@@@ -1279,6 -1247,9 +1280,6 @@@ ifdef ZLIB_PAT
  endif
  EXTLIBS += -lz
  
 -ifndef NO_POSIX_ONLY_PROGRAMS
 -      PROGRAM_OBJS += daemon.o
 -endif
  ifndef NO_OPENSSL
        OPENSSL_LIBSSL = -lssl
        ifdef OPENSSLDIR
@@@ -1372,17 -1343,6 +1373,17 @@@ ifdef NO_STRTOK_
        COMPAT_CFLAGS += -DNO_STRTOK_R
        COMPAT_OBJS += compat/strtok_r.o
  endif
 +ifdef NO_FNMATCH
 +      COMPAT_CFLAGS += -Icompat/fnmatch
 +      COMPAT_CFLAGS += -DNO_FNMATCH
 +      COMPAT_OBJS += compat/fnmatch/fnmatch.o
 +else
 +ifdef NO_FNMATCH_CASEFOLD
 +      COMPAT_CFLAGS += -Icompat/fnmatch
 +      COMPAT_CFLAGS += -DNO_FNMATCH_CASEFOLD
 +      COMPAT_OBJS += compat/fnmatch/fnmatch.o
 +endif
 +endif
  ifdef NO_SETENV
        COMPAT_CFLAGS += -DNO_SETENV
        COMPAT_OBJS += compat/setenv.o
@@@ -1401,15 -1361,6 +1402,15 @@@ endi
  ifdef NO_SYS_SELECT_H
        BASIC_CFLAGS += -DNO_SYS_SELECT_H
  endif
 +ifdef NO_SYS_POLL_H
 +      BASIC_CFLAGS += -DNO_SYS_POLL_H
 +endif
 +ifdef NO_INTTYPES_H
 +      BASIC_CFLAGS += -DNO_INTTYPES_H
 +endif
 +ifdef NO_INITGROUPS
 +      BASIC_CFLAGS += -DNO_INITGROUPS
 +endif
  ifdef NO_MMAP
        COMPAT_CFLAGS += -DNO_MMAP
        COMPAT_OBJS += compat/mmap.o
@@@ -1447,11 -1398,9 +1448,11 @@@ endi
  endif
  ifdef NO_INET_NTOP
        LIB_OBJS += compat/inet_ntop.o
 +      BASIC_CFLAGS += -DNO_INET_NTOP
  endif
  ifdef NO_INET_PTON
        LIB_OBJS += compat/inet_pton.o
 +      BASIC_CFLAGS += -DNO_INET_PTON
  endif
  
  ifdef NO_ICONV
@@@ -1466,10 -1415,6 +1467,10 @@@ ifdef NO_DEFLATE_BOUN
        BASIC_CFLAGS += -DNO_DEFLATE_BOUND
  endif
  
 +ifdef NO_POSIX_GOODIES
 +      BASIC_CFLAGS += -DNO_POSIX_GOODIES
 +endif
 +
  ifdef BLK_SHA1
        SHA1_HEADER = "block-sha1/sha1.h"
        LIB_OBJS += block-sha1/sha1.o
@@@ -1983,7 -1928,7 +1984,7 @@@ git-%$X: %.o $(GITLIBS
  
  git-imap-send$X: imap-send.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 -              $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
 +              $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
  
  git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
diff --combined builtin/pack-objects.c
index 3cbeb299d172c51b8ab6940a836efdf8a1a8e4ce,7471c92b9323839d0fe675366c7c7ebd1872a081..f027b3abb4093e0382b3e612f03b634cee2c6b1d
@@@ -1298,23 -1298,9 +1298,23 @@@ static int try_delta(struct unpacked *t
                read_lock();
                src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz);
                read_unlock();
 -              if (!src->data)
 +              if (!src->data) {
 +                      if (src_entry->preferred_base) {
 +                              static int warned = 0;
 +                              if (!warned++)
 +                                      warning("object %s cannot be read",
 +                                              sha1_to_hex(src_entry->idx.sha1));
 +                              /*
 +                               * Those objects are not included in the
 +                               * resulting pack.  Be resilient and ignore
 +                               * them if they can't be read, in case the
 +                               * pack could be created nevertheless.
 +                               */
 +                              return 0;
 +                      }
                        die("object %s cannot be read",
                            sha1_to_hex(src_entry->idx.sha1));
 +              }
                if (sz != src_size)
                        die("object %s inconsistent object length (%lu vs %lu)",
                            sha1_to_hex(src_entry->idx.sha1), sz, src_size);
@@@ -1543,7 -1529,7 +1543,7 @@@ static void try_to_free_from_threads(si
        read_unlock();
  }
  
- try_to_free_t old_try_to_free_routine;
static try_to_free_t old_try_to_free_routine;
  
  /*
   * The main thread waits on the condition that (at least) one of the workers
diff --combined environment.c
index 76e4dee273340e01855ffbce355741ed5d369009,95777f4c7f2ca653254ad857f6f6833d2040e0b5..913b0580afbe6414af4d08518f5f356817bd0cb6
@@@ -21,7 -21,6 +21,7 @@@ int prefer_symlink_refs
  int is_bare_repository_cfg = -1; /* unspecified */
  int log_all_ref_updates = -1; /* unspecified */
  int warn_ambiguous_refs = 1;
 +int unique_abbrev_extra_length;
  int repository_format_version;
  const char *git_commit_encoding;
  const char *git_log_output_encoding;
@@@ -172,6 -171,43 +172,43 @@@ char *get_object_directory(void
        return git_object_dir;
  }
  
+ int odb_mkstemp(char *template, size_t limit, const char *pattern)
+ {
+       int fd;
+       /*
+        * we let the umask do its job, don't try to be more
+        * restrictive except to remove write permission.
+        */
+       int mode = 0444;
+       snprintf(template, limit, "%s/%s",
+                get_object_directory(), pattern);
+       fd = git_mkstemp_mode(template, mode);
+       if (0 <= fd)
+               return fd;
+       /* slow path */
+       /* some mkstemp implementations erase template on failure */
+       snprintf(template, limit, "%s/%s",
+                get_object_directory(), pattern);
+       safe_create_leading_directories(template);
+       return xmkstemp_mode(template, mode);
+ }
+ int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1)
+ {
+       int fd;
+       snprintf(name, namesz, "%s/pack/pack-%s.keep",
+                get_object_directory(), sha1_to_hex(sha1));
+       fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
+       if (0 <= fd)
+               return fd;
+       /* slow path */
+       safe_create_leading_directories(name);
+       return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
+ }
  char *get_index_file(void)
  {
        if (!git_index_file)
@@@ -193,14 -229,3 +230,14 @@@ int set_git_dir(const char *path
        setup_git_env();
        return 0;
  }
 +
 +const char *get_log_output_encoding(void)
 +{
 +      return git_log_output_encoding ? git_log_output_encoding
 +              : get_commit_output_encoding();
 +}
 +
 +const char *get_commit_output_encoding(void)
 +{
 +      return git_commit_encoding ? git_commit_encoding : "UTF-8";
 +}
diff --combined git-compat-util.h
index 490f96974417b00cd98de046ab1d6853425c3335,029162eccce14e743cf08cf428a024bc341e11b3..d6d269f138b06791ba6e8712b06036f00a73c7e3
  #include <assert.h>
  #include <regex.h>
  #include <utime.h>
 +#include <syslog.h>
 +#ifndef NO_SYS_POLL_H
 +#include <sys/poll.h>
 +#else
 +#include <poll.h>
 +#endif
  #ifndef __MINGW32__
  #include <sys/wait.h>
 -#include <sys/poll.h>
  #include <sys/socket.h>
  #include <sys/ioctl.h>
  #include <termios.h>
  #include <arpa/inet.h>
  #include <netdb.h>
  #include <pwd.h>
 +#ifndef NO_INTTYPES_H
  #include <inttypes.h>
 +#else
 +#include <stdint.h>
 +#endif
  #if defined(__CYGWIN__)
  #undef _XOPEN_SOURCE
  #include <grp.h>
@@@ -395,14 -386,6 +395,14 @@@ static inline void *gitmempcpy(void *de
  }
  #endif
  
 +#ifdef NO_INET_PTON
 +int inet_pton(int af, const char *src, void *dst);
 +#endif
 +
 +#ifdef NO_INET_NTOP
 +const char *inet_ntop(int af, const void *src, char *dst, size_t size);
 +#endif
 +
  extern void release_pack_memory(size_t, int);
  
  typedef void (*try_to_free_t)(size_t);
@@@ -421,6 -404,7 +421,7 @@@ extern ssize_t xwrite(int fd, const voi
  extern int xdup(int fd);
  extern FILE *xfdopen(int fd, const char *mode);
  extern int xmkstemp(char *template);
+ extern int xmkstemp_mode(char *template, int mode);
  extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
  extern int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1);
  
diff --combined sha1_file.c
index c5023703c910ac961fa22bed4e5446e0b9b17ab3,e0d2496bcd6ffbaccae9aebd935a908514ac78a5..1cafdfa617a833ec757b481826dc62282be8f374
@@@ -35,8 -35,6 +35,8 @@@ static size_t sz_fmt(size_t s) { retur
  
  const unsigned char null_sha1[20];
  
 +static int git_open_noatime(const char *name, struct packed_git *p);
 +
  int safe_create_leading_directories(char *path)
  {
        char *pos = path + offset_1st_component(path);
@@@ -300,7 -298,7 +300,7 @@@ static void read_info_alternates(const 
        int fd;
  
        sprintf(path, "%s/%s", relative_base, alt_file_name);
 -      fd = open(path, O_RDONLY);
 +      fd = git_open_noatime(path, NULL);
        if (fd < 0)
                return;
        if (fstat(fd, &st) || (st.st_size == 0)) {
@@@ -413,7 -411,7 +413,7 @@@ static int check_packed_git_idx(const c
        struct pack_idx_header *hdr;
        size_t idx_size;
        uint32_t version, nr, i, *index;
 -      int fd = open(path, O_RDONLY);
 +      int fd = git_open_noatime(path, p);
        struct stat st;
  
        if (fd < 0)
@@@ -578,6 -576,21 +578,21 @@@ void release_pack_memory(size_t need, i
                ; /* nothing */
  }
  
+ void *xmmap(void *start, size_t length,
+       int prot, int flags, int fd, off_t offset)
+ {
+       void *ret = mmap(start, length, prot, flags, fd, offset);
+       if (ret == MAP_FAILED) {
+               if (!length)
+                       return NULL;
+               release_pack_memory(length, fd);
+               ret = mmap(start, length, prot, flags, fd, offset);
+               if (ret == MAP_FAILED)
+                       die_errno("Out of memory? mmap failed");
+       }
+       return ret;
+ }
  void close_pack_windows(struct packed_git *p)
  {
        while (p->windows) {
@@@ -657,7 -670,9 +672,7 @@@ static int open_packed_git_1(struct pac
        if (!p->index_data && open_pack_index(p))
                return error("packfile %s index unavailable", p->pack_name);
  
 -      p->pack_fd = open(p->pack_name, O_RDONLY);
 -      while (p->pack_fd < 0 && errno == EMFILE && unuse_one_window(p, -1))
 -              p->pack_fd = open(p->pack_name, O_RDONLY);
 +      p->pack_fd = git_open_noatime(p->pack_name, p);
        if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
                return -1;
  
@@@ -803,11 -818,22 +818,22 @@@ static struct packed_git *alloc_packed_
        return p;
  }
  
+ static void try_to_free_pack_memory(size_t size)
+ {
+       release_pack_memory(size, -1);
+ }
  struct packed_git *add_packed_git(const char *path, int path_len, int local)
  {
+       static int have_set_try_to_free_routine;
        struct stat st;
        struct packed_git *p = alloc_packed_git(path_len + 2);
  
+       if (!have_set_try_to_free_routine) {
+               have_set_try_to_free_routine = 1;
+               set_try_to_free_routine(try_to_free_pack_memory);
+       }
        /*
         * Make sure a corresponding .pack file exists and that
         * the index looks sane.
@@@ -874,7 -900,7 +900,7 @@@ static void prepare_packed_git_one(cha
        sprintf(path, "%s/pack", objdir);
        len = strlen(path);
        dir = opendir(path);
 -      while (!dir && errno == EMFILE && unuse_one_window(packed_git, -1))
 +      while (!dir && errno == EMFILE && unuse_one_window(NULL, -1))
                dir = opendir(path);
        if (!dir) {
                if (errno != ENOENT)
@@@ -1003,7 -1029,7 +1029,7 @@@ static void mark_bad_packed_object(stru
        p->num_bad_objects++;
  }
  
 -static int has_packed_and_bad(const unsigned char *sha1)
 +static const struct packed_git *has_packed_and_bad(const unsigned char *sha1)
  {
        struct packed_git *p;
        unsigned i;
        for (p = packed_git; p; p = p->next)
                for (i = 0; i < p->num_bad_objects; i++)
                        if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
 -                              return 1;
 -      return 0;
 +                              return p;
 +      return NULL;
  }
  
  int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)
        return hashcmp(sha1, real_sha1) ? -1 : 0;
  }
  
 -static int git_open_noatime(const char *name)
 +static int git_open_noatime(const char *name, struct packed_git *p)
  {
        static int sha1_file_open_flag = O_NOATIME;
 -      int fd = open(name, O_RDONLY | sha1_file_open_flag);
  
 -      /* Might the failure be due to O_NOATIME? */
 -      if (fd < 0 && errno != ENOENT && sha1_file_open_flag) {
 -              fd = open(name, O_RDONLY);
 +      for (;;) {
 +              int fd = open(name, O_RDONLY | sha1_file_open_flag);
                if (fd >= 0)
 +                      return fd;
 +
 +              /* Might the failure be insufficient file descriptors? */
 +              if (errno == EMFILE) {
 +                      if (unuse_one_window(p, -1))
 +                              continue;
 +                      else
 +                              return -1;
 +              }
 +
 +              /* Might the failure be due to O_NOATIME? */
 +              if (errno != ENOENT && sha1_file_open_flag) {
                        sha1_file_open_flag = 0;
 +                      continue;
 +              }
 +
 +              return -1;
        }
 -      return fd;
  }
  
  static int open_sha1_file(const unsigned char *sha1)
        char *name = sha1_file_name(sha1);
        struct alternate_object_database *alt;
  
 -      fd = git_open_noatime(name);
 +      fd = git_open_noatime(name, NULL);
        if (fd >= 0)
                return fd;
  
        for (alt = alt_odb_list; alt; alt = alt->next) {
                name = alt->name;
                fill_sha1_path(name, sha1);
 -              fd = git_open_noatime(alt->base);
 +              fd = git_open_noatime(alt->base, NULL);
                if (fd >= 0)
                        return fd;
        }
@@@ -2092,48 -2105,36 +2118,48 @@@ static void *read_object(const unsigne
        return read_packed_sha1(sha1, type, size);
  }
  
 +/*
 + * This function dies on corrupt objects; the callers who want to
 + * deal with them should arrange to call read_object() and give error
 + * messages themselves.
 + */
  void *read_sha1_file_repl(const unsigned char *sha1,
                          enum object_type *type,
                          unsigned long *size,
                          const unsigned char **replacement)
  {
        const unsigned char *repl = lookup_replace_object(sha1);
 -      void *data = read_object(repl, type, size);
 +      void *data;
        char *path;
 +      const struct packed_git *p;
 +
 +      errno = 0;
 +      data = read_object(repl, type, size);
 +      if (data) {
 +              if (replacement)
 +                      *replacement = repl;
 +              return data;
 +      }
 +
 +      if (errno != ENOENT)
 +              die_errno("failed to read object %s", sha1_to_hex(sha1));
  
        /* die if we replaced an object with one that does not exist */
 -      if (!data && repl != sha1)
 +      if (repl != sha1)
                die("replacement %s not found for %s",
                    sha1_to_hex(repl), sha1_to_hex(sha1));
  
 -      /* legacy behavior is to die on corrupted objects */
 -      if (!data) {
 -              if (has_loose_object(repl)) {
 -                      path = sha1_file_name(sha1);
 -                      die("loose object %s (stored in %s) is corrupted", sha1_to_hex(repl), path);
 -              }
 -              if (has_packed_and_bad(repl)) {
 -                      path = sha1_pack_name(sha1);
 -                      die("packed object %s (stored in %s) is corrupted", sha1_to_hex(repl), path);
 -              }
 +      if (has_loose_object(repl)) {
 +              path = sha1_file_name(sha1);
 +              die("loose object %s (stored in %s) is corrupt",
 +                  sha1_to_hex(repl), path);
        }
  
 -      if (replacement)
 -              *replacement = repl;
 +      if ((p = has_packed_and_bad(repl)) != NULL)
 +              die("packed object %s (stored in %s) is corrupt",
 +                  sha1_to_hex(repl), p->pack_name);
  
 -      return data;
 +      return NULL;
  }
  
  void *read_object_with_reference(const unsigned char *sha1,
@@@ -2325,7 -2326,7 +2351,7 @@@ static int write_loose_object(const uns
  
        filename = sha1_file_name(sha1);
        fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
 -      while (fd < 0 && errno == EMFILE && unuse_one_window(packed_git, -1))
 +      while (fd < 0 && errno == EMFILE && unuse_one_window(NULL, -1))
                fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
        if (fd < 0) {
                if (errno == EACCES)
diff --combined sha1_name.c
index b48b91c507e597405274dc5aa3edc98ee5149bdc,32522c0fe531604152d6f3f9bf5dd08d1a73085b..2c3a5fb363ff9b11a971b45e85819b2c0aaad157
@@@ -206,9 -206,7 +206,9 @@@ const char *find_unique_abbrev(const un
                if (exists
                    ? !status
                    : status == SHORT_NAME_NOT_FOUND) {
 -                      hex[len] = 0;
 +                      int cut_at = len + unique_abbrev_extra_length;
 +                      cut_at = (cut_at < 40) ? cut_at : 40;
 +                      hex[cut_at] = 0;
                        return hex;
                }
                len++;
@@@ -936,6 -934,24 +936,24 @@@ int interpret_branch_name(const char *n
        return len;
  }
  
+ int strbuf_branchname(struct strbuf *sb, const char *name)
+ {
+       int len = strlen(name);
+       if (interpret_branch_name(name, sb) == len)
+               return 0;
+       strbuf_add(sb, name, len);
+       return len;
+ }
+ int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
+ {
+       strbuf_branchname(sb, name);
+       if (name[0] == '-')
+               return CHECK_REF_FORMAT_ERROR;
+       strbuf_splice(sb, 0, 0, "refs/heads/", 11);
+       return check_ref_format(sb->buf);
+ }
  /*
   * This is like "get_sha1_basic()", except it allows "sha1 expressions",
   * notably "xyz^" for "parent of xyz"
@@@ -1071,7 -1087,6 +1089,7 @@@ int get_sha1_with_context_1(const char 
                struct cache_entry *ce;
                int pos;
                if (namelen > 2 && name[1] == '/')
 +                      /* don't need mode for commit */
                        return get_sha1_oneline(name + 2, sha1);
                if (namelen < 3 ||
                    name[2] != ':' ||
                                break;
                        if (ce_stage(ce) == stage) {
                                hashcpy(sha1, ce->sha1);
 +                              oc->mode = ce->ce_mode;
                                return 0;
                        }
                        pos++;