Code

Merge branch 'maint'
authorJunio C Hamano <junkio@cox.net>
Tue, 24 Apr 2007 07:08:16 +0000 (00:08 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 24 Apr 2007 07:08:16 +0000 (00:08 -0700)
* maint:
  Documentation/git-reset.txt: suggest git commit --amend in example.
  Build RPM with ETC_GITCONFIG=/etc/gitconfig
  Ignore all man sections as they are generated files.
  Fix typo in git-am: s/Was is/Was it/
  Reverse the order of -b and --track in the man page.
  dir.c(common_prefix): Fix two bugs

Conflicts:

git.spec.in

1  2 
dir.c
git.spec.in

diff --combined dir.c
index 6564a929ff66cdffca0666e175c9361149b25b5e,602282bd1b198a7a0cef0707c738b4eda0d3ccef..d3063520b03c9c5f608cbd9e97f6b414adb4c5af
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -7,16 -7,6 +7,16 @@@
   */
  #include "cache.h"
  #include "dir.h"
 +#include "refs.h"
 +
 +struct path_simplify {
 +      int len;
 +      const char *path;
 +};
 +
 +static int read_directory_recursive(struct dir_struct *dir,
 +      const char *path, const char *base, int baselen,
 +      int check_only, const struct path_simplify *simplify);
  
  int common_prefix(const char **pathspec)
  {
@@@ -34,8 -24,9 +34,9 @@@
        prefix = slash - path + 1;
        while ((next = *++pathspec) != NULL) {
                int len = strlen(next);
-               if (len >= prefix && !memcmp(path, next, len))
+               if (len >= prefix && !memcmp(path, next, prefix))
                        continue;
+               len = prefix - 1;
                for (;;) {
                        if (!len)
                                return 0;
@@@ -291,136 -282,15 +292,136 @@@ struct dir_entry *dir_add_name(struct d
        return ent;
  }
  
 -static int dir_exists(const char *dirname, int len)
 +enum exist_status {
 +      index_nonexistent = 0,
 +      index_directory,
 +      index_gitdir,
 +};
 +
 +/*
 + * The index sorts alphabetically by entry name, which
 + * means that a gitlink sorts as '\0' at the end, while
 + * a directory (which is defined not as an entry, but as
 + * the files it contains) will sort with the '/' at the
 + * end.
 + */
 +static enum exist_status directory_exists_in_index(const char *dirname, int len)
  {
        int pos = cache_name_pos(dirname, len);
 -      if (pos >= 0)
 +      if (pos < 0)
 +              pos = -pos-1;
 +      while (pos < active_nr) {
 +              struct cache_entry *ce = active_cache[pos++];
 +              unsigned char endchar;
 +
 +              if (strncmp(ce->name, dirname, len))
 +                      break;
 +              endchar = ce->name[len];
 +              if (endchar > '/')
 +                      break;
 +              if (endchar == '/')
 +                      return index_directory;
 +              if (!endchar && S_ISDIRLNK(ntohl(ce->ce_mode)))
 +                      return index_gitdir;
 +      }
 +      return index_nonexistent;
 +}
 +
 +/*
 + * When we find a directory when traversing the filesystem, we
 + * have three distinct cases:
 + *
 + *  - ignore it
 + *  - see it as a directory
 + *  - recurse into it
 + *
 + * and which one we choose depends on a combination of existing
 + * git index contents and the flags passed into the directory
 + * traversal routine.
 + *
 + * Case 1: If we *already* have entries in the index under that
 + * directory name, we always recurse into the directory to see
 + * all the files.
 + *
 + * Case 2: If we *already* have that directory name as a gitlink,
 + * we always continue to see it as a gitlink, regardless of whether
 + * there is an actual git directory there or not (it might not
 + * be checked out as a subproject!)
 + *
 + * Case 3: if we didn't have it in the index previously, we
 + * have a few sub-cases:
 + *
 + *  (a) if "show_other_directories" is true, we show it as
 + *      just a directory, unless "hide_empty_directories" is
 + *      also true and the directory is empty, in which case
 + *      we just ignore it entirely.
 + *  (b) if it looks like a git directory, and we don't have
 + *      'no_dirlinks' set we treat it as a gitlink, and show it
 + *      as a directory.
 + *  (c) otherwise, we recurse into it.
 + */
 +enum directory_treatment {
 +      show_directory,
 +      ignore_directory,
 +      recurse_into_directory,
 +};
 +
 +static enum directory_treatment treat_directory(struct dir_struct *dir,
 +      const char *dirname, int len,
 +      const struct path_simplify *simplify)
 +{
 +      /* The "len-1" is to strip the final '/' */
 +      switch (directory_exists_in_index(dirname, len-1)) {
 +      case index_directory:
 +              return recurse_into_directory;
 +
 +      case index_gitdir:
 +              if (dir->show_other_directories)
 +                      return ignore_directory;
 +              return show_directory;
 +
 +      case index_nonexistent:
 +              if (dir->show_other_directories)
 +                      break;
 +              if (!dir->no_dirlinks) {
 +                      unsigned char sha1[20];
 +                      if (resolve_gitlink_ref(dirname, "HEAD", sha1) == 0)
 +                              return show_directory;
 +              }
 +              return recurse_into_directory;
 +      }
 +
 +      /* This is the "show_other_directories" case */
 +      if (!dir->hide_empty_directories)
 +              return show_directory;
 +      if (!read_directory_recursive(dir, dirname, dirname, len, 1, simplify))
 +              return ignore_directory;
 +      return show_directory;
 +}
 +
 +/*
 + * This is an inexact early pruning of any recursive directory
 + * reading - if the path cannot possibly be in the pathspec,
 + * return true, and we'll skip it early.
 + */
 +static int simplify_away(const char *path, int pathlen, const struct path_simplify *simplify)
 +{
 +      if (simplify) {
 +              for (;;) {
 +                      const char *match = simplify->path;
 +                      int len = simplify->len;
 +
 +                      if (!match)
 +                              break;
 +                      if (len > pathlen)
 +                              len = pathlen;
 +                      if (!memcmp(path, match, len))
 +                              return 0;
 +                      simplify++;
 +              }
                return 1;
 -      pos = -pos-1;
 -      if (pos >= active_nr) /* can't */
 -              return 0;
 -      return !strncmp(active_cache[pos]->name, dirname, len);
 +      }
 +      return 0;
  }
  
  /*
   * Also, we ignore the name ".git" (even if it is not a directory).
   * That likely will not change.
   */
 -static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only)
 +static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only, const struct path_simplify *simplify)
  {
        DIR *fdir = opendir(path);
        int contents = 0;
                             !strcmp(de->d_name + 1, "git")))
                                continue;
                        len = strlen(de->d_name);
 +                      /* Ignore overly long pathnames! */
 +                      if (len + baselen + 8 > sizeof(fullname))
 +                              continue;
                        memcpy(fullname + baselen, de->d_name, len+1);
 +                      if (simplify_away(fullname, baselen + len, simplify))
 +                              continue;
                        if (excluded(dir, fullname) != dir->show_ignored) {
                                if (!dir->show_ignored || DTYPE(de) != DT_DIR) {
                                        continue;
                        case DT_DIR:
                                memcpy(fullname + baselen + len, "/", 2);
                                len++;
 -                              if (dir->show_other_directories &&
 -                                  !dir_exists(fullname, baselen + len)) {
 -                                      if (dir->hide_empty_directories &&
 -                                          !read_directory_recursive(dir,
 -                                                  fullname, fullname,
 -                                                  baselen + len, 1))
 -                                              continue;
 +                              switch (treat_directory(dir, fullname, baselen + len, simplify)) {
 +                              case show_directory:
                                        break;
 +                              case recurse_into_directory:
 +                                      contents += read_directory_recursive(dir,
 +                                              fullname, fullname, baselen + len, 0, simplify);
 +                                      continue;
 +                              case ignore_directory:
 +                                      continue;
                                }
 -
 -                              contents += read_directory_recursive(dir,
 -                                      fullname, fullname, baselen + len, 0);
 -                              continue;
 +                              break;
                        case DT_REG:
                        case DT_LNK:
                                break;
@@@ -520,61 -387,8 +521,61 @@@ static int cmp_name(const void *p1, con
                                  e2->name, e2->len);
  }
  
 -int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen)
 +/*
 + * Return the length of the "simple" part of a path match limiter.
 + */
 +static int simple_length(const char *match)
 +{
 +      const char special[256] = {
 +              [0] = 1, ['?'] = 1,
 +              ['\\'] = 1, ['*'] = 1,
 +              ['['] = 1
 +      };
 +      int len = -1;
 +
 +      for (;;) {
 +              unsigned char c = *match++;
 +              len++;
 +              if (special[c])
 +                      return len;
 +      }
 +}
 +
 +static struct path_simplify *create_simplify(const char **pathspec)
 +{
 +      int nr, alloc = 0;
 +      struct path_simplify *simplify = NULL;
 +
 +      if (!pathspec)
 +              return NULL;
 +
 +      for (nr = 0 ; ; nr++) {
 +              const char *match;
 +              if (nr >= alloc) {
 +                      alloc = alloc_nr(alloc);
 +                      simplify = xrealloc(simplify, alloc * sizeof(*simplify));
 +              }
 +              match = *pathspec++;
 +              if (!match)
 +                      break;
 +              simplify[nr].path = match;
 +              simplify[nr].len = simple_length(match);
 +      }
 +      simplify[nr].path = NULL;
 +      simplify[nr].len = 0;
 +      return simplify;
 +}
 +
 +static void free_simplify(struct path_simplify *simplify)
  {
 +      if (simplify)
 +              free(simplify);
 +}
 +
 +int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec)
 +{
 +      struct path_simplify *simplify = create_simplify(pathspec);
 +
        /*
         * Make sure to do the per-directory exclude for all the
         * directories leading up to our base.
                }
        }
  
 -      read_directory_recursive(dir, path, base, baselen, 0);
 +      read_directory_recursive(dir, path, base, baselen, 0, simplify);
 +      free_simplify(simplify);
        qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
        return dir->nr;
  }
diff --combined git.spec.in
index f0746ed78c79739885ca9c32af27d3ee9ed4a974,87197d10e19107883716e3ced5b4eb38c3d933be..556bdda7aa2ec7a99c7668390c60cdc69eed74f5
@@@ -1,7 -1,4 +1,7 @@@
  # Pass --without docs to rpmbuild if you don't want the documentation
 +
 +%define python_path /usr/bin/python
 +
  Name:                 git
  Version:      @@VERSION@@
  Release:      1%{?dist}
@@@ -12,7 -9,7 +12,7 @@@ URL:           http://kernel.org/pub/software/s
  Source:       http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
  BuildRequires:        zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel  %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
  BuildRoot:    %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 -Requires:     git-core, git-svn, git-cvs, git-arch, git-email, gitk, git-gui, perl-Git
 +Requires:     git-core, git-svn, git-cvs, git-arch, git-email, gitk, git-gui, git-p4, perl-Git
  
  %description
  Git is a fast, scalable, distributed revision control system with an
@@@ -53,13 -50,6 +53,13 @@@ Requires:       git-core = %{version}-%
  %description arch
  Git tools for importing Arch repositories.
  
 +%package p4
 +Summary:        Git tools for importing Perforce repositories
 +Group:          Development/Tools
 +Requires:       git-core = %{version}-%{release}, python
 +%description p4
 +Git tools for importing Perforce repositories.
 +
  %package email
  Summary:        Git tools for sending email
  Group:          Development/Tools
@@@ -95,23 -85,25 +95,25 @@@ Perl interface to Gi
  %setup -q
  
  %build
 -make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease \
 +make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_P4IMPORT=YesPlease \
+      ETC_GITCONFIG=/etc/gitconfig \
 -     prefix=%{_prefix} all %{!?_without_docs: doc}
 +     prefix=%{_prefix} PYTHON_PATH=%{python_path} all %{!?_without_docs: doc}
  
  %install
  rm -rf $RPM_BUILD_ROOT
  make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" DESTDIR=$RPM_BUILD_ROOT \
 -     WITH_OWN_SUBPROCESS_PY=YesPlease \
 +     WITH_P4IMPORT=YesPlease prefix=%{_prefix} mandir=%{_mandir} \
+      ETC_GITCONFIG=/etc/gitconfig \
 -     prefix=%{_prefix} mandir=%{_mandir} INSTALLDIRS=vendor \
 -     install %{!?_without_docs: install-doc}
 +     PYTHON_PATH=%{python_path} \
 +     INSTALLDIRS=vendor install %{!?_without_docs: install-doc}
  find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
  find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';'
  find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';'
  
 -(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
 +(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "p4import|archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
  (find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files
  %if %{!?_without_docs:1}0
 -(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
 +(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "p4import|archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
  %else
  rm -rf $RPM_BUILD_ROOT%{_mandir}
  %endif
@@@ -143,13 -135,6 +145,13 @@@ rm -rf $RPM_BUILD_ROO
  %{!?_without_docs: %{_mandir}/man1/git-archimport.1*}
  %{!?_without_docs: %doc Documentation/git-archimport.html }
  
 +%files p4
 +%defattr(-,root,root)
 +%doc Documentation/git-p4import.txt
 +%{_bindir}/git-p4import
 +%{!?_without_docs: %{_mandir}/man1/git-p4import.1*}
 +%{!?_without_docs: %doc Documentation/git-p4import.html }
 +
  %files email
  %defattr(-,root,root)
  %doc Documentation/*email*.txt
  %{!?_without_docs: %doc Documentation/*.html }
  
  %changelog
 +* Tue Mar 27 2007 Eygene Ryabinkin <rea-git@codelabs.ru>
 +- Added the git-p4 package: Perforce import stuff.
 +
  * Mon Feb 13 2007 Nicolas Pitre <nico@cam.org>
  - Update core package description (Git isn't as stupid as it used to be)