GIT 1.1.0
authorJunio C Hamano <junkio@cox.net>
Sun, 8 Jan 2006 22:22:19 +0000 (14:22 -0800)
committerJunio C Hamano <junkio@cox.net>
Sun, 8 Jan 2006 22:22:19 +0000 (14:22 -0800)
1  2 
Makefile
cache.h
commit.c
describe.c
ls-files.c
receive-pack.c
diff --combined Makefile
index 1b6caf85bb11e00c9d579bf79662bb05ca80827f,119a45f7bc5e547ca8d199edc94ac285d2ab5c38..c9c15b5ff2255dbaa08dcde9e7b37080fef74cc3
+++ b/Makefile
@@@ -55,9 -55,7 +55,9 @@@ all
  # Define USE_STDEV below if you want git to care about the underlying device
  # change being considered an inode change from the update-cache perspective.
  
 -GIT_VERSION = 1.0.8
 +GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
 +      @sh ./GIT-VERSION-GEN
 +-include GIT-VERSION-FILE
  
  # CFLAGS and LDFLAGS are for the users to override from the command line.
  
@@@ -137,8 -135,7 +137,8 @@@ PROGRAMS = 
        git-unpack-objects$X git-update-index$X git-update-server-info$X \
        git-upload-pack$X git-verify-pack$X git-write-tree$X \
        git-update-ref$X git-symbolic-ref$X git-check-ref-format$X \
 -      git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X
 +      git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \
 +      git-describe$X
  
  # what 'all' will build and 'install' will install.
  ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) git$X
@@@ -371,7 -368,7 +371,7 @@@ all: $(ALL_PROGRAMS
  all:
        $(MAKE) -C templates
  
 -git$X: git.c $(LIB_FILE) Makefile
 +git$X: git.c $(LIB_FILE)
        $(CC) -DGIT_EXEC_PATH='"$(bindir)"' -DGIT_VERSION='"$(GIT_VERSION)"' \
                $(CFLAGS) $(COMPAT_CFLAGS) -o $@ $(filter %.c,$^) $(LIB_FILE)
  
@@@ -400,12 -397,8 +400,12 @@@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : 
  git-cherry-pick: git-revert
        cp $< $@
  
 -# format-patch records GIT_VERSION
 -git-format-patch: Makefile
 +# These can record GIT_VERSION
 +git$X git.spec \
 +      $(patsubst %.sh,%,$(SCRIPT_SH)) \
 +      $(patsubst %.perl,%,$(SCRIPT_PERL)) \
 +      $(patsubst %.py,%,$(SCRIPT_PYTHON)) \
 +      : GIT-VERSION-FILE
  
  %.o: %.c
        $(CC) -o $*.o -c $(ALL_CFLAGS) $<
@@@ -481,7 -474,7 +481,7 @@@ install-doc
  
  ### Maintainer's dist rules
  
 -git.spec: git.spec.in Makefile
 +git.spec: git.spec.in
        sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@
  
  GIT_TARNAME=git-$(GIT_VERSION)
@@@ -496,12 -489,6 +496,6 @@@ dist: git.spec git-tar-tre
  rpm: dist
        $(RPMBUILD) -ta $(GIT_TARNAME).tar.gz
  
- deb: dist
-       rm -rf $(GIT_TARNAME)
-       $(TAR) zxf $(GIT_TARNAME).tar.gz
-       dpkg-source -b $(GIT_TARNAME)
-       cd $(GIT_TARNAME) && fakeroot debian/rules binary
  ### Cleaning rules
  
  clean:
        rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo
        rm -rf $(GIT_TARNAME)
        rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
-       rm -f git-core_$(GIT_VERSION)-*.dsc
-       rm -f git-*_$(GIT_VERSION)-*.deb
        $(MAKE) -C Documentation/ clean
        $(MAKE) -C templates clean
        $(MAKE) -C t/ clean
 +      rm -f GIT-VERSION-FILE
 +
 +.PHONY: all install clean
 +.PHONY: .FORCE-GIT-VERSION-FILE
  
diff --combined cache.h
index a99fb3ce7d3423d51f5a0829a4bd20f0cd5ca0e1,5fd2687636026c2000b2f39e383af00b45c3627c..29c9e819d61ccb93167d5f22c8280f75014872f9
+++ b/cache.h
@@@ -81,7 -81,7 +81,7 @@@ struct cache_entry 
        unsigned int ce_size;
        unsigned char sha1[20];
        unsigned short ce_flags;
-       char name[0];
+       char name[FLEX_ARRAY]; /* more */
  };
  
  #define CE_NAMEMASK  (0x0fff)
@@@ -159,7 -159,6 +159,7 @@@ extern void rollback_index_file(struct 
  extern int trust_executable_bit;
  extern int only_use_symrefs;
  extern int diff_rename_limit_default;
 +extern int shared_repository;
  
  #define GIT_REPO_VERSION 0
  extern int repository_format_version;
@@@ -184,7 -183,6 +184,7 @@@ extern const unsigned char null_sha1[20
  
  int git_mkstemp(char *path, size_t n, const char *template);
  
 +int adjust_shared_perm(const char *path);
  int safe_create_leading_directories(char *path);
  char *safe_strncpy(char *, const char *, size_t);
  char *enter_repo(char *path, int strict);
@@@ -259,7 -257,7 +259,7 @@@ extern int checkout_entry(struct cache_
  extern struct alternate_object_database {
        struct alternate_object_database *next;
        char *name;
-       char base[0]; /* more */
+       char base[FLEX_ARRAY]; /* more */
  } *alt_odb_list;
  extern void prepare_alt_odb(void);
  
@@@ -273,7 -271,8 +273,8 @@@ extern struct packed_git 
        unsigned int pack_use_cnt;
        int pack_local;
        unsigned char sha1[20];
-       char pack_name[0]; /* something like ".git/objects/pack/xxxxx.pack" */
+       /* something like ".git/objects/pack/xxxxx.pack" */
+       char pack_name[FLEX_ARRAY]; /* more */
  } *packed_git;
  
  struct pack_entry {
@@@ -288,7 -287,7 +289,7 @@@ struct ref 
        unsigned char new_sha1[20];
        unsigned char force;
        struct ref *peer_ref; /* when renaming */
-       char name[0];
+       char name[FLEX_ARRAY]; /* more */
  };
  
  extern int git_connect(int fd[2], char *url, const char *prog);
diff --combined commit.c
index e9a29caa27fbdd94810abbc4fd9c44e06c81265c,fb02ba609b00d48a8e0e4c127cdc292a438bf9f3..56efc69f1f4bf1568eaa549bed16f7cc2cd669ba
+++ b/commit.c
@@@ -1,6 -1,6 +1,6 @@@
+ #include "cache.h"
  #include "tag.h"
  #include "commit.h"
- #include "cache.h"
  
  int save_commit_buffer = 1;
  
@@@ -352,19 -352,6 +352,19 @@@ struct commit *pop_most_recent_commit(s
        return ret;
  }
  
 +void clear_commit_marks(struct commit *commit, unsigned int mark)
 +{
 +      struct commit_list *parents;
 +
 +      parents = commit->parents;
 +      commit->object.flags &= ~mark;
 +      while (parents) {
 +              if (parents->item && parents->item->object.parsed)
 +                      clear_commit_marks(parents->item, mark);
 +              parents = parents->next;
 +      }
 +}
 +
  /*
   * Generic support for pretty-printing the header
   */
diff --combined describe.c
index 00fa02adccda98998fcaa8feb733a71dedfee55f,0000000000000000000000000000000000000000..a0180f548ec950fe10ae4f759c13842cbcf03285
mode 100644,000000..100644
--- /dev/null
@@@ -1,164 -1,0 +1,164 @@@
-       char path[];
 +#include "cache.h"
 +#include "commit.h"
 +#include "tag.h"
 +#include "refs.h"
 +
 +#define SEEN (1u << 0)
 +
 +static const char describe_usage[] =
 +"git-describe [--all] [--tags] [--abbrev=<n>] <committish>*";
 +
 +static int all = 0;   /* Default to annotated tags only */
 +static int tags = 0;  /* But allow any tags if --tags is specified */
 +
 +#define DEFAULT_ABBREV 8 /* maybe too many */
 +static int abbrev = DEFAULT_ABBREV;
 +
 +static int names = 0, allocs = 0;
 +static struct commit_name {
 +      const struct commit *commit;
 +      int prio; /* annotated tag = 2, tag = 1, head = 0 */
++      char path[FLEX_ARRAY]; /* more */
 +} **name_array = NULL;
 +
 +static struct commit_name *match(struct commit *cmit)
 +{
 +      int i = names;
 +      struct commit_name **p = name_array;
 +
 +      while (i-- > 0) {
 +              struct commit_name *n = *p++;
 +              if (n->commit == cmit)
 +                      return n;
 +      }
 +      return NULL;
 +}
 +
 +static void add_to_known_names(const char *path,
 +                             const struct commit *commit,
 +                             int prio)
 +{
 +      int idx;
 +      int len = strlen(path)+1;
 +      struct commit_name *name = xmalloc(sizeof(struct commit_name) + len);
 +
 +      name->commit = commit;
 +      name->prio = prio; 
 +      memcpy(name->path, path, len);
 +      idx = names;
 +      if (idx >= allocs) {
 +              allocs = (idx + 50) * 3 / 2;
 +              name_array = xrealloc(name_array, allocs*sizeof(*name_array));
 +      }
 +      name_array[idx] = name;
 +      names = ++idx;
 +}
 +
 +static int get_name(const char *path, const unsigned char *sha1)
 +{
 +      struct commit *commit = lookup_commit_reference_gently(sha1, 1);
 +      struct object *object;
 +      int prio;
 +
 +      if (!commit)
 +              return 0;
 +      object = parse_object(sha1);
 +      /* If --all, then any refs are used.
 +       * If --tags, then any tags are used.
 +       * Otherwise only annotated tags are used.
 +       */
 +      if (!strncmp(path, "refs/tags/", 10)) {
 +              if (object->type == tag_type)
 +                      prio = 2;
 +              else
 +                      prio = 1;
 +      }
 +      else
 +              prio = 0;
 +
 +      if (!all) {
 +              if (!prio)
 +                      return 0;
 +              if (!tags && prio < 2)
 +                      return 0;
 +      }
 +      add_to_known_names(all ? path + 5 : path + 10, commit, prio);
 +      return 0;
 +}
 +
 +static int compare_names(const void *_a, const void *_b)
 +{
 +      struct commit_name *a = *(struct commit_name **)_a;
 +      struct commit_name *b = *(struct commit_name **)_b;
 +      unsigned long a_date = a->commit->date;
 +      unsigned long b_date = b->commit->date;
 +
 +      if (a->prio != b->prio)
 +              return b->prio - a->prio;
 +      return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
 +}
 +
 +static void describe(struct commit *cmit)
 +{
 +      struct commit_list *list;
 +      static int initialized = 0;
 +      struct commit_name *n;
 +
 +      if (!initialized) {
 +              initialized = 1;
 +              for_each_ref(get_name);
 +              qsort(name_array, names, sizeof(*name_array), compare_names);
 +      }
 +
 +      n = match(cmit);
 +      if (n) {
 +              printf("%s\n", n->path);
 +              return;
 +      }
 +
 +      list = NULL;
 +      commit_list_insert(cmit, &list);
 +      while (list) {
 +              struct commit *c = pop_most_recent_commit(&list, SEEN);
 +              n = match(c);
 +              if (n) {
 +                      printf("%s-g%s\n", n->path,
 +                             find_unique_abbrev(cmit->object.sha1, abbrev));
 +                      break;
 +              }
 +      }
 +      clear_commit_marks(cmit, SEEN);
 +}
 +
 +int main(int argc, char **argv)
 +{
 +      int i;
 +
 +      for (i = 1; i < argc; i++) {
 +              const char *arg = argv[i];
 +              unsigned char sha1[20];
 +              struct commit *cmit;
 +
 +              if (!strcmp(arg, "--all")) {
 +                      all = 1;
 +                      continue;
 +              }
 +              if (!strcmp(arg, "--tags")) {
 +                      tags = 1;
 +                      continue;
 +              }
 +              if (!strncmp(arg, "--abbrev=", 9)) {
 +                      abbrev = strtoul(arg + 9, NULL, 10);
 +                      if (abbrev < 4 || 40 <= abbrev)
 +                              abbrev = DEFAULT_ABBREV;
 +                      continue;
 +              }
 +              if (get_sha1(arg, sha1) < 0)
 +                      usage(describe_usage);
 +              cmit = lookup_commit_reference(sha1);
 +              if (!cmit)
 +                      usage(describe_usage);
 +              describe(cmit);
 +      }
 +      return 0;
 +}
diff --combined ls-files.c
index b29fe1be7e9f48bafafd2bd197c7238ee251b2cd,74ec8c0aeeb52a3bed8a0ac9da8fb9ba5ef66187..6af3b091b049d8ded1999405b4da7191f2b36a4c
@@@ -19,7 -19,6 +19,7 @@@ static int show_stage = 0
  static int show_unmerged = 0;
  static int show_modified = 0;
  static int show_killed = 0;
 +static int show_other_directories = 0;
  static int line_terminator = '\n';
  
  static int prefix_len = 0, prefix_offset = 0;
@@@ -209,7 -208,7 +209,7 @@@ static int excluded(const char *pathnam
  
  struct nond_on_fs {
        int len;
-       char name[0];
+       char name[FLEX_ARRAY]; /* more */
  };
  
  static struct nond_on_fs **dir;
@@@ -234,17 -233,6 +234,17 @@@ static void add_name(const char *pathna
        dir[nr_dir++] = ent;
  }
  
 +static int dir_exists(const char *dirname, int len)
 +{
 +      int pos = cache_name_pos(dirname, len);
 +      if (pos >= 0)
 +              return 1;
 +      pos = -pos-1;
 +      if (pos >= active_nr) /* can't */
 +              return 0;
 +      return !strncmp(active_cache[pos]->name, dirname, len);
 +}
 +
  /*
   * Read a directory tree. We currently ignore anything but
   * directories, regular files and symlinks. That's because git
@@@ -293,12 -281,8 +293,12 @@@ static void read_directory(const char *
                                /* fallthrough */
                        case DT_DIR:
                                memcpy(fullname + baselen + len, "/", 2);
 +                              len++;
 +                              if (show_other_directories &&
 +                                  !dir_exists(fullname, baselen + len))
 +                                      break;
                                read_directory(fullname, fullname,
 -                                             baselen + len + 1);
 +                                             baselen + len);
                                continue;
                        case DT_REG:
                        case DT_LNK:
@@@ -638,10 -622,6 +638,10 @@@ int main(int argc, const char **argv
                        show_killed = 1;
                        continue;
                }
 +              if (!strcmp(arg, "--directory")) {
 +                      show_other_directories = 1;
 +                      continue;
 +              }
                if (!strcmp(arg, "-u") || !strcmp(arg, "--unmerged")) {
                        /* There's no point in showing unmerged unless
                         * you also show the stage information.
diff --combined receive-pack.c
index e79de917b542eb35d6b5752837b25ccae897646e,ce986fe11cd8989b439f070e9bea5d68b6711758..f847ec2b54b74e2b9bee7bde8fccbaa8ee569573
@@@ -8,36 -8,23 +8,36 @@@ static const char receive_pack_usage[] 
  
  static const char unpacker[] = "git-unpack-objects";
  
 +static int report_status = 0;
 +
 +static char capabilities[] = "report-status";
 +static int capabilities_sent = 0;
 +
  static int show_ref(const char *path, const unsigned char *sha1)
  {
 -      packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
 +      if (capabilities_sent)
 +              packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
 +      else
 +              packet_write(1, "%s %s%c%s\n",
 +                           sha1_to_hex(sha1), path, 0, capabilities);
 +      capabilities_sent = 1;
        return 0;
  }
  
  static void write_head_info(void)
  {
        for_each_ref(show_ref);
 +      if (!capabilities_sent)
 +              show_ref("capabilities^{}", null_sha1);
 +
  }
  
  struct command {
        struct command *next;
 -      unsigned char updated;
 +      const char *error_string;
        unsigned char old_sha1[20];
        unsigned char new_sha1[20];
-       char ref_name[0];
+       char ref_name[FLEX_ARRAY]; /* more */
  };
  
  static struct command *commands = NULL;
@@@ -84,37 -71,33 +84,37 @@@ static int run_update_hook(const char *
        case 0:
                return 0;
        case -ERR_RUN_COMMAND_FORK:
 -              die("hook fork failed");
 +              return error("hook fork failed");
        case -ERR_RUN_COMMAND_EXEC:
 -              die("hook execute failed");
 +              return error("hook execute failed");
        case -ERR_RUN_COMMAND_WAITPID:
 -              die("waitpid failed");
 +              return error("waitpid failed");
        case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 -              die("waitpid is confused");
 +              return error("waitpid is confused");
        case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
 -              fprintf(stderr, "%s died of signal\n", update_hook);
 -              return -1;
 +              return error("%s died of signal\n", update_hook);
        case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
 -              die("%s died strangely", update_hook);
 +              return error("%s died strangely", update_hook);
        default:
                error("%s exited with error code %d", update_hook, -code);
                return -code;
        }
  }
  
 -static int update(const char *name,
 -                unsigned char *old_sha1, unsigned char *new_sha1)
 +static int update(struct command *cmd)
  {
 +      const char *name = cmd->ref_name;
 +      unsigned char *old_sha1 = cmd->old_sha1;
 +      unsigned char *new_sha1 = cmd->new_sha1;
        char new_hex[60], *old_hex, *lock_name;
        int newfd, namelen, written;
  
 -      if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5))
 +      cmd->error_string = NULL;
 +      if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5)) {
 +              cmd->error_string = "funny refname";
                return error("refusing to create funny ref '%s' locally",
                             name);
 +      }
  
        namelen = strlen(name);
        lock_name = xmalloc(namelen + 10);
  
        strcpy(new_hex, sha1_to_hex(new_sha1));
        old_hex = sha1_to_hex(old_sha1);
 -      if (!has_sha1_file(new_sha1))
 +      if (!has_sha1_file(new_sha1)) {
 +              cmd->error_string = "bad pack";
                return error("unpack should have generated %s, "
                             "but I can't find it!", new_hex);
 -
 +      }
        safe_create_leading_directories(lock_name);
  
        newfd = open(lock_name, O_CREAT | O_EXCL | O_WRONLY, 0666);
 -      if (newfd < 0)
 +      if (newfd < 0) {
 +              cmd->error_string = "can't lock";
                return error("unable to create %s (%s)",
                             lock_name, strerror(errno));
 +      }
  
        /* Write the ref with an ending '\n' */
        new_hex[40] = '\n';
        close(newfd);
        if (written != 41) {
                unlink(lock_name);
 +              cmd->error_string = "can't write";
                return error("unable to write %s", lock_name);
        }
        if (verify_old_ref(name, old_hex) < 0) {
                unlink(lock_name);
 +              cmd->error_string = "raced";
                return error("%s changed during push", name);
        }
        if (run_update_hook(name, old_hex, new_hex)) {
                unlink(lock_name);
 +              cmd->error_string = "hook declined";
                return error("hook declined to update %s\n", name);
        }
        else if (rename(lock_name, name) < 0) {
                unlink(lock_name);
 +              cmd->error_string = "can't rename";
                return error("unable to replace %s", name);
        }
        else {
@@@ -182,7 -158,7 +182,7 @@@ static void run_update_post_hook(struc
        if (access(update_post_hook, X_OK) < 0)
                return;
        for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
 -              if (!cmd_p->updated)
 +              if (cmd_p->error_string)
                        continue;
                argc++;
        }
        argv[0] = update_post_hook;
  
        for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
 -              if (!cmd_p->updated)
 +              if (cmd_p->error_string)
                        continue;
                argv[argc] = xmalloc(strlen(cmd_p->ref_name) + 1);
                strcpy(argv[argc], cmd_p->ref_name);
@@@ -209,7 -185,8 +209,7 @@@ static void execute_commands(void
        struct command *cmd = commands;
  
        while (cmd) {
 -              cmd->updated = !update(cmd->ref_name,
 -                                     cmd->old_sha1, cmd->new_sha1);
 +              update(cmd);
                cmd = cmd->next;
        }
        run_update_post_hook(commands);
@@@ -222,8 -199,7 +222,8 @@@ static void read_head_info(void
                static char line[1000];
                unsigned char old_sha1[20], new_sha1[20];
                struct command *cmd;
 -              int len;
 +              char *refname;
 +              int len, reflen;
  
                len = packet_read_line(0, line, sizeof(line));
                if (!len)
                    line[81] != ' ' ||
                    get_sha1_hex(line, old_sha1) ||
                    get_sha1_hex(line + 41, new_sha1))
 -                      die("protocol error: expected old/new/ref, got '%s'", line);
 +                      die("protocol error: expected old/new/ref, got '%s'",
 +                          line);
 +
 +              refname = line + 82;
 +              reflen = strlen(refname);
 +              if (reflen + 82 < len) {
 +                      if (strstr(refname + reflen + 1, "report-status"))
 +                              report_status = 1;
 +              }
                cmd = xmalloc(sizeof(struct command) + len - 80);
                memcpy(cmd->old_sha1, old_sha1, 20);
                memcpy(cmd->new_sha1, new_sha1, 20);
                memcpy(cmd->ref_name, line + 82, len - 81);
 +              cmd->error_string = "n/a (unpacker error)";
                cmd->next = NULL;
                *p = cmd;
                p = &cmd->next;
        }
  }
  
 -static void unpack(void)
 +static const char *unpack(int *error_code)
  {
        int code = run_command(unpacker, NULL);
 +
 +      *error_code = 0;
        switch (code) {
        case 0:
 -              return;
 +              return NULL;
        case -ERR_RUN_COMMAND_FORK:
 -              die("unpack fork failed");
 +              return "unpack fork failed";
        case -ERR_RUN_COMMAND_EXEC:
 -              die("unpack execute failed");
 +              return "unpack execute failed";
        case -ERR_RUN_COMMAND_WAITPID:
 -              die("waitpid failed");
 +              return "waitpid failed";
        case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 -              die("waitpid is confused");
 +              return "waitpid is confused";
        case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
 -              die("%s died of signal", unpacker);
 +              return "unpacker died of signal";
        case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
 -              die("%s died strangely", unpacker);
 +              return "unpacker died strangely";
        default:
 -              die("%s exited with error code %d", unpacker, -code);
 +              *error_code = -code;
 +              return "unpacker exited with error code";
 +      }
 +}
 +
 +static void report(const char *unpack_status)
 +{
 +      struct command *cmd;
 +      packet_write(1, "unpack %s\n",
 +                   unpack_status ? unpack_status : "ok");
 +      for (cmd = commands; cmd; cmd = cmd->next) {
 +              if (!cmd->error_string)
 +                      packet_write(1, "ok %s\n",
 +                                   cmd->ref_name);
 +              else
 +                      packet_write(1, "ng %s %s\n",
 +                                   cmd->ref_name, cmd->error_string);
        }
 +      packet_flush(1);
  }
  
  int main(int argc, char **argv)
  
        read_head_info();
        if (commands) {
 -              unpack();
 -              execute_commands();
 +              int code;
 +              const char *unpack_status = unpack(&code);
 +              if (!unpack_status)
 +                      execute_commands();
 +              if (report_status)
 +                      report(unpack_status);
        }
        return 0;
  }