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>::
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;;
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::
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;
}
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);
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];
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;
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;
}
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)
diff_free_filepair(p);
}
- if (opts & DIFF_PICKAXE_REGEX) {
+ if (opts & DIFF_PICKAXE_REGEX)
regfree(®ex);
- }
free(q->queue);
*q = outq;
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
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);
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);
#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
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;
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)};
}
# double check that there are no missing non-merge commits
my (@incomplete) = check_cherry_pick(
$merge_base, $merge_tip,
+ $parents,
@$ranges,
);
'git ls-files --error-unmatch foo bar'
test_done
-1
--- /dev/null
+#!/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
#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))
static int line_contains_alnum(const char *ptr, long size)
{
while (size--)
- if (isalnum(*(ptr++)))
+ if (isalnum((unsigned char)*(ptr++)))
return 1;
return 0;
}
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;
}
* 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);
}
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');