Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Wed, 6 Oct 2010 19:10:02 +0000 (12:10 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 6 Oct 2010 19:10:02 +0000 (12:10 -0700)
* maint:
Documentation/git-clone: describe --mirror more verbosely
do not depend on signed integer overflow
work around buggy S_ISxxx(m) implementations
xdiff: cast arguments for ctype functions to unsigned char
init: plug tiny one-time memory leak
diffcore-pickaxe.c: remove unnecessary curly braces
t3020 (ls-files-error-unmatch): remove stray '1' from end of file
setup: make sure git dir path is in a permanent buffer
environment.c: remove unused variable
git-svn: fix processing of decorated commit hashes
git-svn: check_cherry_pick should exclude commits already in our history
Documentation/git-svn: discourage "noMetadata"

16 files changed:
Documentation/git-clone.txt
Documentation/git-svn.txt
builtin/index-pack.c
builtin/init-db.c
builtin/pack-objects.c
builtin/unpack-objects.c
cache.h
diffcore-pickaxe.c
environment.c
git-compat-util.h
git-svn.perl
t/t3020-ls-files-error-unmatch.sh
t/t9157-git-svn-fetch-merge.sh [new file with mode: 0644]
xdiff/xmacros.h
xdiff/xmerge.c
xdiff/xutils.c
index dc7d3d17b151d05827925fdcd2806945e2e278cb..ab7293351d283e7ee3a8275c534c3667d6b4d696 100644 (file)
@@ -128,7 +128,12 @@ objects from the source repository into a pack in the cloned repository.
        configuration variables are created.
 
 --mirror::
-       Set up a mirror of the remote repository.  This implies `--bare`.
+       Set up a mirror of the source repository.  This implies `--bare`.
+       Compared to `--bare`, `--mirror` not only maps local branches of the
+       source to local branches of the target, it maps all refs (including
+       remote branches, notes etc.) and sets up a refspec configuration such
+       that all these refs are overwritten by a `git remote update` in the
+       target repository.
 
 --origin <name>::
 -o <name>::
index 4b84d08fc87c13f6db371ecc52710bd09865d784..be8a51fd062df8a3c3680c724b2b6241e5f5fe33 100644 (file)
@@ -56,6 +56,8 @@ COMMANDS
        as well, they take precedence.
 --no-metadata;;
        Set the 'noMetadata' option in the [svn-remote] config.
+       This option is not recommended, please read the 'svn.noMetadata'
+       section of this manpage before using this option.
 --use-svm-props;;
        Set the 'useSvmProps' option in the [svn-remote] config.
 --use-svnsync-props;;
@@ -597,13 +599,22 @@ svn.noMetadata::
 svn-remote.<name>.noMetadata::
        This gets rid of the 'git-svn-id:' lines at the end of every commit.
 +
-If you lose your .git/svn/git-svn/.rev_db file, 'git svn' will not
-be able to rebuild it and you won't be able to fetch again,
-either.  This is fine for one-shot imports.
+This option can only be used for one-shot imports as 'git svn'
+will not be able to fetch again without metadata. Additionally,
+if you lose your .git/svn/**/.rev_map.* files, 'git svn' will not
+be able to rebuild them.
 +
 The 'git svn log' command will not work on repositories using
 this, either.  Using this conflicts with the 'useSvmProps'
 option for (hopefully) obvious reasons.
++
+This option is NOT recommended as it makes it difficult to track down
+old references to SVN revision numbers in existing documentation, bug
+reports and archives.  If you plan to eventually migrate from SVN to git
+and are certain about dropping SVN history, consider
+linkgit:git-filter-branch[1] instead.  filter-branch also allows
+reformating of metadata for ease-of-reading and rewriting authorship
+info for non-"svn.authorsFile" users.
 
 svn.useSvmProps::
 svn-remote.<name>.useSvmProps::
index 2e680d7a7ac3495c9d6bd10e0fa6a6ae28bb8670..e243d9d22ea90603f0ed7754e943763055fe4bbd 100644 (file)
@@ -161,7 +161,7 @@ static void use(int bytes)
        input_offset += bytes;
 
        /* make sure off_t is sufficiently large not to wrap */
-       if (consumed_bytes > consumed_bytes + bytes)
+       if (signed_add_overflows(consumed_bytes, bytes))
                die("pack too large for current definition of off_t");
        consumed_bytes += bytes;
 }
index 0271285fad6ad532a6133838f7188498476fd77b..9d4886c71675f2bc50671ea284875ebae9a34735 100644 (file)
@@ -294,11 +294,26 @@ static int create_default_files(const char *template_path)
        return reinit;
 }
 
+static void create_object_directory(void)
+{
+       const char *object_directory = get_object_directory();
+       int len = strlen(object_directory);
+       char *path = xmalloc(len + 40);
+
+       memcpy(path, object_directory, len);
+
+       safe_create_dir(object_directory, 1);
+       strcpy(path+len, "/pack");
+       safe_create_dir(path, 1);
+       strcpy(path+len, "/info");
+       safe_create_dir(path, 1);
+
+       free(path);
+}
+
 int init_db(const char *template_dir, unsigned int flags)
 {
-       const char *sha1_dir;
-       char *path;
-       int len, reinit;
+       int reinit;
 
        safe_create_dir(get_git_dir(), 0);
 
@@ -313,16 +328,7 @@ int init_db(const char *template_dir, unsigned int flags)
 
        reinit = create_default_files(template_dir);
 
-       sha1_dir = get_object_directory();
-       len = strlen(sha1_dir);
-       path = xmalloc(len + 40);
-       memcpy(path, sha1_dir, len);
-
-       safe_create_dir(sha1_dir, 1);
-       strcpy(path+len, "/pack");
-       safe_create_dir(path, 1);
-       strcpy(path+len, "/info");
-       safe_create_dir(path, 1);
+       create_object_directory();
 
        if (shared_repository) {
                char buf[10];
index 3756cf36ee5dd6fb963af2ab62b0d474fcabd4bb..d5a8db1bb6c14b02db9f7f534fcbaf4dc46994ba 100644 (file)
@@ -431,7 +431,7 @@ static int write_one(struct sha1file *f,
        written_list[nr_written++] = &e->idx;
 
        /* make sure off_t is sufficiently large not to wrap */
-       if (*offset > *offset + size)
+       if (signed_add_overflows(*offset, size))
                die("pack too large for current definition of off_t");
        *offset += size;
        return 1;
index 685566e0b5e458c510fdf989744d63dda29e28f0..f63973c9143c4109a3d1e40df9ec66a32498fe00 100644 (file)
@@ -83,7 +83,7 @@ static void use(int bytes)
        offset += bytes;
 
        /* make sure off_t is sufficiently large not to wrap */
-       if (consumed_bytes > consumed_bytes + bytes)
+       if (signed_add_overflows(consumed_bytes, bytes))
                die("pack too large for current definition of off_t");
        consumed_bytes += bytes;
 }
diff --git a/cache.h b/cache.h
index 2ef2fa3a5e166d94e5e981ca7c76afad13236e7e..3d5ed51989d6c118062c0709eae41fcb3cc6543b 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -277,9 +277,16 @@ static inline int ce_to_dtype(const struct cache_entry *ce)
        else
                return DT_UNKNOWN;
 }
-#define canon_mode(mode) \
-       (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
-       S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK)
+static inline unsigned int canon_mode(unsigned int mode)
+{
+       if (S_ISREG(mode))
+               return S_IFREG | ce_permissions(mode);
+       if (S_ISLNK(mode))
+               return S_IFLNK;
+       if (S_ISDIR(mode))
+               return S_IFDIR;
+       return S_IFGITLINK;
+}
 
 #define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
 #define cache_entry_size(len) flexible_size(cache_entry,len)
index 84195e47aa0a0e2fbeeb8a56d255ff5c6f42efe7..38570999c34f061524c3544892c53431db4f1623 100644 (file)
@@ -269,9 +269,8 @@ static void diffcore_pickaxe_count(struct diff_options *o)
                                diff_free_filepair(p);
                }
 
-       if (opts & DIFF_PICKAXE_REGEX) {
+       if (opts & DIFF_PICKAXE_REGEX)
                regfree(&regex);
-       }
 
        free(q->queue);
        *q = outq;
index 2d0c3153791d7cceffb12f50dd5a7716b8c0a8c0..de5581fe51d532231b0121bd2ef2e46669015bda 100644 (file)
@@ -64,7 +64,7 @@ char *git_work_tree_cfg;
 static char *work_tree;
 
 static const char *git_dir;
-static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
+static char *git_object_dir, *git_index_file, *git_graft_file;
 
 /*
  * Repository-local GIT_* environment variables
@@ -87,8 +87,10 @@ const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = {
 static void setup_git_env(void)
 {
        git_dir = getenv(GIT_DIR_ENVIRONMENT);
-       if (!git_dir)
+       if (!git_dir) {
                git_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
+               git_dir = git_dir ? xstrdup(git_dir) : NULL;
+       }
        if (!git_dir)
                git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
        git_object_dir = getenv(DB_ENVIRONMENT);
@@ -96,8 +98,6 @@ static void setup_git_env(void)
                git_object_dir = xmalloc(strlen(git_dir) + 9);
                sprintf(git_object_dir, "%s/objects", git_dir);
        }
-       git_refs_dir = xmalloc(strlen(git_dir) + 6);
-       sprintf(git_refs_dir, "%s/refs", git_dir);
        git_index_file = getenv(INDEX_ENVIRONMENT);
        if (!git_index_file) {
                git_index_file = xmalloc(strlen(git_dir) + 7);
index 81883e7270daadafb4d827e894fa4645ff2e2b66..2af8d3edbe35dce35e940c5cccb91f9e06ebeff8 100644 (file)
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
 #define bitsizeof(x)  (CHAR_BIT * sizeof(x))
 
+#define maximum_signed_value_of_type(a) \
+    (INTMAX_MAX >> (bitsizeof(intmax_t) - bitsizeof(a)))
+
+/*
+ * Signed integer overflow is undefined in C, so here's a helper macro
+ * to detect if the sum of two integers will overflow.
+ *
+ * Requires: a >= 0, typeof(a) equals typeof(b)
+ */
+#define signed_add_overflows(a, b) \
+    ((b) > maximum_signed_value_of_type(a) - (a))
+
 #ifdef __GNUC__
 #define TYPEOF(x) (__typeof__(x))
 #else
index 9b046b693fe82c992b3844bf6e8f79214dfa7a59..18cfb2466d11aa28a795e3dabac70e236061fbe9 100755 (executable)
@@ -1513,7 +1513,8 @@ sub cmt_sha2rev_batch {
 
 sub working_head_info {
        my ($head, $refs) = @_;
-       my @args = ('log', '--no-color', '--first-parent', '--pretty=medium');
+       my @args = qw/log --no-color --no-decorate --first-parent
+                     --pretty=medium/;
        my ($fh, $ctx) = command_output_pipe(@args, $head);
        my $hash;
        my %max;
@@ -3118,9 +3119,10 @@ sub _rev_list {
 sub check_cherry_pick {
        my $base = shift;
        my $tip = shift;
+       my $parents = shift;
        my @ranges = @_;
        my %commits = map { $_ => 1 }
-               _rev_list("--no-merges", $tip, "--not", $base);
+               _rev_list("--no-merges", $tip, "--not", $base, @$parents);
        for my $range ( @ranges ) {
                delete @commits{_rev_list($range)};
        }
@@ -3296,6 +3298,7 @@ sub find_extra_svn_parents {
                # double check that there are no missing non-merge commits
                my (@incomplete) = check_cherry_pick(
                        $merge_base, $merge_tip,
+                       $parents,
                        @$ranges,
                       );
 
index a7d8187169a36f708bd7dc39d97604dd9cc21565..ca01053bcc88806aae9abde5892b8c163b3936d0 100755 (executable)
@@ -26,4 +26,3 @@ test_expect_success \
     'git ls-files --error-unmatch foo bar'
 
 test_done
-1
diff --git a/t/t9157-git-svn-fetch-merge.sh b/t/t9157-git-svn-fetch-merge.sh
new file mode 100644 (file)
index 0000000..da582c5
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Steven Walter
+#
+
+test_description='git svn merge detection'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize source svn repo' '
+       svn_cmd mkdir -m x "$svnrepo"/trunk &&
+       svn_cmd mkdir -m x "$svnrepo"/branches &&
+       svn_cmd co "$svnrepo"/trunk "$SVN_TREE" &&
+       (
+               cd "$SVN_TREE" &&
+               touch foo &&
+               svn add foo &&
+               svn commit -m "initial commit" &&
+               svn cp -m branch "$svnrepo"/trunk "$svnrepo"/branches/branch1 &&
+               touch bar &&
+               svn add bar &&
+               svn commit -m x &&
+               svn cp -m branch "$svnrepo"/trunk "$svnrepo"/branches/branch2 &&
+               svn switch "$svnrepo"/branches/branch1 &&
+               touch baz &&
+               svn add baz &&
+               svn commit -m x &&
+               svn switch "$svnrepo"/trunk &&
+               svn merge "$svnrepo"/branches/branch1 &&
+               svn commit -m "merge" &&
+               svn switch "$svnrepo"/branches/branch1 &&
+               svn commit -m x &&
+               svn switch "$svnrepo"/branches/branch2 &&
+               svn merge "$svnrepo"/branches/branch1 &&
+               svn commit -m "merge branch1" &&
+               svn switch "$svnrepo"/trunk &&
+               svn merge "$svnrepo"/branches/branch2 &&
+               svn resolved baz &&
+               svn commit -m "merge branch2"
+       ) &&
+       rm -rf "$SVN_TREE"
+'
+
+test_expect_success 'clone svn repo' '
+       git svn init -s "$svnrepo" &&
+       git svn fetch
+'
+
+test_expect_success 'verify merge commit' 'git rev-parse HEAD^2'
+
+test_done
index 8ef232cfad12d706aaafe705bf16c546f3597182..165a895a93e04b33ca7c8f3839ee85e0eccb4a07 100644 (file)
@@ -30,6 +30,7 @@
 #define XDL_MAX(a, b) ((a) > (b) ? (a): (b))
 #define XDL_ABS(v) ((v) >= 0 ? (v): -(v))
 #define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
+#define XDL_ISSPACE(c) (isspace((unsigned char)(c)))
 #define XDL_ADDBITS(v,b)       ((v) + ((v) >> (b)))
 #define XDL_MASKBITS(b)                ((1UL << (b)) - 1)
 #define XDL_HASHLONG(v,b)      (XDL_ADDBITS((unsigned long)(v), b) & XDL_MASKBITS(b))
index 6d6fc1bc5e01be7305ec5101f43645a1dce69bd3..9e13b25abc90350de4488276074dc282edc216b1 100644 (file)
@@ -336,7 +336,7 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
 static int line_contains_alnum(const char *ptr, long size)
 {
        while (size--)
-               if (isalnum(*(ptr++)))
+               if (isalnum((unsigned char)*(ptr++)))
                        return 1;
        return 0;
 }
index 22f9bd692c2706136b4938bbcb2e0fc3dab212b8..ab6503460f760356a393a3c7b3b8438213e1ee94 100644 (file)
@@ -211,18 +211,18 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
                        if (l1[i1++] != l2[i2++])
                                return 0;
                skip_ws:
-                       while (i1 < s1 && isspace(l1[i1]))
+                       while (i1 < s1 && XDL_ISSPACE(l1[i1]))
                                i1++;
-                       while (i2 < s2 && isspace(l2[i2]))
+                       while (i2 < s2 && XDL_ISSPACE(l2[i2]))
                                i2++;
                }
        } else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) {
                while (i1 < s1 && i2 < s2) {
-                       if (isspace(l1[i1]) && isspace(l2[i2])) {
+                       if (XDL_ISSPACE(l1[i1]) && XDL_ISSPACE(l2[i2])) {
                                /* Skip matching spaces and try again */
-                               while (i1 < s1 && isspace(l1[i1]))
+                               while (i1 < s1 && XDL_ISSPACE(l1[i1]))
                                        i1++;
-                               while (i2 < s2 && isspace(l2[i2]))
+                               while (i2 < s2 && XDL_ISSPACE(l2[i2]))
                                        i2++;
                                continue;
                        }
@@ -241,13 +241,13 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
         * while there still are characters remaining on both lines.
         */
        if (i1 < s1) {
-               while (i1 < s1 && isspace(l1[i1]))
+               while (i1 < s1 && XDL_ISSPACE(l1[i1]))
                        i1++;
                if (s1 != i1)
                        return 0;
        }
        if (i2 < s2) {
-               while (i2 < s2 && isspace(l2[i2]))
+               while (i2 < s2 && XDL_ISSPACE(l2[i2]))
                        i2++;
                return (s2 == i2);
        }
@@ -260,10 +260,10 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
        char const *ptr = *data;
 
        for (; ptr < top && *ptr != '\n'; ptr++) {
-               if (isspace(*ptr)) {
+               if (XDL_ISSPACE(*ptr)) {
                        const char *ptr2 = ptr;
                        int at_eol;
-                       while (ptr + 1 < top && isspace(ptr[1])
+                       while (ptr + 1 < top && XDL_ISSPACE(ptr[1])
                                        && ptr[1] != '\n')
                                ptr++;
                        at_eol = (top <= ptr + 1 || ptr[1] == '\n');