--- /dev/null
+GIT v1.6.2.2 Release Notes
+==========================
+
+Fixes since v1.6.2.1
+--------------------
+
+* A longstanding confusing description of what --pickaxe option of
+ git-diff does has been clarified in the documentation.
+
+* "git diff --pickaxe-regexp" did not count overlapping matches
+ correctly.
+
+* "git-fetch" in a repository that was not cloned from anywhere said
+ it cannot find 'origin', which was hard to understand for new people.
+
+* "git-format-patch --numbered-files --stdout" did not have to die of
+ incompatible options; it now simply ignores --numbered-files as no files
+ are produced anyway.
+
+* "git-ls-files --deleted" did not work well with GIT_DIR&GIT_WORK_TREE.
+
+* "git-read-tree A B C..." without -m option has been broken for a long
+ time.
+
+* git-send-email ignored --in-reply-to when --no-thread was given.
+
+* 'git-submodule add' did not tolerate extra slashes and ./ in the path it
+ accepted from the command line; it now is more lenient.
+
+* git-svn misbehaved when the project contained a path that began with
+ two dashes.
+
+* import-zips script (in contrib) did not compute the common directory
+ prefix correctly.
+
+Many small documentation updates are included as well.
+
+---
+exec >/var/tmp/1
+O=v1.6.2.1-46-gb19293d
+echo O=$(git describe maint)
+git shortlog --no-merges $O..maint
number.
-S<string>::
- Look for differences that contain the change in <string>.
+ Look for differences that introduce or remove an instance of
+ <string>. Note that this is different than the string simply
+ appearing in diff output; see the 'pickaxe' entry in
+ linkgit:gitdiffcore[7] for more details.
--pickaxe-all::
When -S finds a change, show all the changes in that
------------
$ tar zxf frotz.tar.gz
$ cd frotz
-$ git-init
+$ git init
$ git add . <1>
$ git commit -m "import of frotz source tree."
$ git tag v2.43 <2>
--origin <name>::
-o <name>::
Instead of using the remote name 'origin' to keep track
- of the upstream repository, use <name> instead.
+ of the upstream repository, use <name>.
--upload-pack <upload-pack>::
-u <upload-pack>::
-r <remote>::
The git remote to import this CVS repository into.
Moves all CVS branches into remotes/<remote>/<branch>
- akin to the 'git-clone' "--use-separate-remote" option.
+ akin to the way 'git-clone' uses 'origin' by default.
-o <branch-for-HEAD>::
When no remote is specified (via -r) the 'HEAD' branch
--numbered-files::
Output file names will be a simple number sequence
without the default first line of the commit appended.
- Mutually exclusive with the --stdout option.
-k::
--keep-subject::
are printed when using -l.
The default is not to print any annotation lines.
If no number is given to `-n`, only the first line is printed.
+ If the tag is not annotated, the commit message is displayed instead.
-l <pattern>::
List tags with names that match the given pattern (or all if no pattern is given).
------------
*
*
-M
+*
|\
* |
| | *
| \ \
| \ \
-M-. \ \
+*-. \ \
|\ \ \ \
| | * | |
| | | | | *
| | | | | *
-| | | | | M
+| | | | | *
| | | | | |\
| | | | | | *
| * | | | | |
-| | | | | M \
+| | | | | * \
| | | | | |\ |
| | | | * | | |
| | | | * | | |
-Documentation/RelNotes-1.6.2.1.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.2.2.txt
\ No newline at end of file
else
remote = remote_get(argv[0]);
+ if (!remote)
+ die("Where do you want to fetch from today?");
+
transport = transport_get(remote, remote->url[0]);
if (verbosity >= 2)
transport->verbose = 1;
if (depth)
set_option(TRANS_OPT_DEPTH, depth);
- if (!transport->url)
- die("Where do you want to fetch from today?");
-
if (argc > 1) {
int j = 0;
refs = xcalloc(argc + 1, sizeof(const char *));
die ("-n and -k are mutually exclusive.");
if (keep_subject && subject_prefix)
die ("--subject-prefix and -k are mutually exclusive.");
- if (numbered_files && use_stdout)
- die ("--numbered-files and --stdout are mutually exclusive.");
argc = setup_revisions(argc, argv, &rev, "HEAD");
if (argc > 1)
}
if (!strcmp(arg, "-d") || !strcmp(arg, "--deleted")) {
show_deleted = 1;
+ require_work_tree = 1;
continue;
}
if (!strcmp(arg, "-m") || !strcmp(arg, "--modified")) {
max_size = trg_entry->delta_size;
ref_depth = trg->depth;
}
- max_size = max_size * (max_depth - src->depth) /
+ max_size = (uint64_t)max_size * (max_depth - src->depth) /
(max_depth - ref_depth + 1);
if (max_size == 0)
return 0;
int i, errs;
struct remote *remote = remote_get(repo);
- if (!remote)
- die("bad repository '%s'", repo);
+ if (!remote) {
+ if (repo)
+ die("bad repository '%s'", repo);
+ die("No destination configured to push to.");
+ }
if (remote->mirror)
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
{
const char *begin = haystack;
const char *last_possible = begin + haystack_len - needle_len;
+ const char *tail = needle;
+ char point;
/*
* The first occurrence of the empty string is deemed to occur at
if (haystack_len < needle_len)
return NULL;
+ point = *tail++;
for (; begin <= last_possible; begin++) {
- if (!memcmp(begin, needle, needle_len))
+ if (*begin == point && !memcmp(begin + 1, tail, needle_len - 1))
return (void *)begin;
}
local cur="${COMP_WORDS[COMP_CWORD]}"
local g="$(git rev-parse --git-dir 2>/dev/null)"
local merge=""
- if [ -f $g/MERGE_HEAD ]; then
+ if [ -f "$g/MERGE_HEAD" ]; then
merge="--merge"
fi
case "$cur" in
local cur="${COMP_WORDS[COMP_CWORD]}"
local g="$(git rev-parse --git-dir 2>/dev/null)"
local merge=""
- if [ -f $g/MERGE_HEAD ]; then
+ if [ -f "$g/MERGE_HEAD" ]; then
merge="--merge"
fi
case "$cur" in
common_prefix = name[:name.rfind('/') + 1]
else:
while not name.startswith(common_prefix):
- common_prefix = name[:name.rfind('/') + 1]
+ last_slash = common_prefix[:-1].rfind('/') + 1
+ common_prefix = common_prefix[:last_slash]
mark[name] = ':' + str(next_mark)
next_mark += 1
no_index ? "--no-index" : "[--no-index]");
diff_setup(&revs->diffopt);
- if (!revs->diffopt.output_format)
- revs->diffopt.output_format = DIFF_FORMAT_PATCH;
for (i = 1; i < argc - 2; ) {
int j;
if (!strcmp(argv[i], "--no-index"))
revs->diffopt.paths = argv + argc - 2;
revs->diffopt.nr_paths = 2;
revs->diffopt.skip_stat_unmatch = 1;
+ if (!revs->diffopt.output_format)
+ revs->diffopt.output_format = DIFF_FORMAT_PATCH;
DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
regex_t *regexp)
{
unsigned int cnt;
- unsigned long offset, sz;
+ unsigned long sz;
const char *data;
if (diff_populate_filespec(one, 0))
return 0;
regmatch_t regmatch;
int flags = 0;
+ assert(data[sz] == '\0');
while (*data && !regexec(regexp, data, 1, ®match, flags)) {
flags |= REG_NOTBOL;
- data += regmatch.rm_so;
- if (*data) data++;
+ data += regmatch.rm_eo;
+ if (*data && regmatch.rm_so == regmatch.rm_eo)
+ data++;
cnt++;
}
} else { /* Classic exact string match */
- /* Yes, I've heard of strstr(), but the thing is *data may
- * not be NUL terminated. Sue me.
- */
- for (offset = 0; offset + len <= sz; offset++) {
- /* we count non-overlapping occurrences of needle */
- if (!memcmp(needle, data + offset, len)) {
- offset += len - 1;
- cnt++;
- }
+ while (sz) {
+ const char *found = memmem(data, sz, needle, len);
+ if (!found)
+ break;
+ sz -= found - data + len;
+ data = found + len;
+ cnt++;
}
}
diff_free_filespec_data(one);
Message-Id: $message_id
X-Mailer: git-send-email $gitversion
";
- if ($thread && $reply_to) {
+ if ($reply_to) {
$header .= "In-Reply-To: $reply_to\n";
$header .= "References: $references\n";
;;
esac
- # strip trailing slashes from path
- path=$(echo "$path" | sed -e 's|/*$||')
-
+ # normalize path:
+ # multiple //; leading ./; /./; /../; trailing /
+ path=$(printf '%s/\n' "$path" |
+ sed -e '
+ s|//*|/|g
+ s|^\(\./\)*||
+ s|/\./|/|g
+ :start
+ s|\([^/]*\)/\.\./||
+ tstart
+ s|/*$||
+ ')
git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
die "'$path' already exists in the index"
return undef if ($gpath eq '');
# remove entire directories.
- if (command('ls-tree', $self->{c}, '--', $gpath) =~ /^040000 tree/) {
+ my ($tree) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
+ =~ /\A040000 tree ([a-f\d]{40})\t\Q$gpath\E\0/);
+ if ($tree) {
my ($ls, $ctx) = command_output_pipe(qw/ls-tree
-r --name-only -z/,
- $self->{c}, '--', $gpath);
+ $tree);
local $/ = "\0";
while (<$ls>) {
chomp;
- $self->{gii}->remove($_);
- print "\tD\t$_\n" unless $::_q;
+ my $rmpath = "$gpath/$_";
+ $self->{gii}->remove($rmpath);
+ print "\tD\t$rmpath\n" unless $::_q;
}
print "\tD\t$gpath/\n" unless $::_q;
command_close_pipe($ls, $ctx);
goto out if is_path_ignored($path);
my $gpath = $self->git_path($path);
- ($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath)
- =~ /^(\d{6}) blob ([a-f\d]{40})\t/);
+ ($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
+ =~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/);
unless (defined $mode && defined $blob) {
die "$path was not found in commit $self->{c} (r$rev)\n";
}
{
struct mailmap_entry *me;
int index;
+ char *p;
+
+ if (old_email)
+ for (p = old_email; *p; p++)
+ *p = tolower(*p);
+ if (new_email)
+ for (p = new_email; *p; p++)
+ *p = tolower(*p);
+
if (old_email == NULL) {
old_email = new_email;
new_email = NULL;
static struct branch *current_branch;
static const char *default_remote_name;
+static int explicit_default_remote_name;
static struct rewrite **rewrite;
static int rewrite_alloc;
if (!value)
return config_error_nonbool(key);
branch->remote_name = xstrdup(value);
- if (branch == current_branch)
+ if (branch == current_branch) {
default_remote_name = branch->remote_name;
+ explicit_default_remote_name = 1;
+ }
} else if (!strcmp(subkey, ".merge")) {
if (!value)
return config_error_nonbool(key);
struct remote *remote_get(const char *name)
{
struct remote *ret;
+ int name_given = 0;
read_config();
- if (!name)
+ if (name)
+ name_given = 1;
+ else {
name = default_remote_name;
+ name_given = explicit_default_remote_name;
+ }
+
ret = make_remote(name, 0);
if (valid_remote_nick(name)) {
if (!ret->url)
if (!ret->url)
read_branches_file(ret);
}
- if (!ret->url)
+ if (name_given && !ret->url)
add_url_alias(ret, name);
if (!ret->url)
return NULL;
ERR_RUN_COMMAND_WAITPID_SIGNAL,
ERR_RUN_COMMAND_WAITPID_NOEXIT,
};
-#define IS_RUN_COMMAND_ERR(x) ((x) <= -ERR_RUN_COMMAND_FORK)
+#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK)
struct child_process {
const char **argv;
fsync_or_die(fd, "sha1 file");
fchmod(fd, 0444);
if (close(fd) != 0)
- die("unable to write sha1 file");
+ die("error when closing sha1 file (%s)", strerror(errno));
}
/* Size of directory component, including the ending '/' */
$(RM) -r test-results
clean:
- $(RM) -r 'trash directory' test-results
+ $(RM) -r 'trash directory'.* test-results
aggregate-results-and-cleanup: $(T)
$(MAKE) aggregate-results
--- /dev/null
+#!/bin/sh
+
+test_description='test multi-tree read-tree without merging'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo one >a &&
+ git add a &&
+ git commit -m initial &&
+ git tag initial &&
+ echo two >b &&
+ git add b &&
+ git commit -m second &&
+ git checkout -b side initial &&
+ echo three >a &&
+ mkdir b &&
+ echo four >b/c &&
+ git add b/c &&
+ git commit -m third
+'
+
+test_expect_success 'multi-read' '
+ git read-tree initial master side &&
+ (echo a; echo b/c) >expect &&
+ git ls-files >actual &&
+ test_cmp expect actual
+'
+
+test_done
+
'
-test "$TEST_RSYNC" && {
+! rsync --help > /dev/null 2> /dev/null &&
+say 'Skipping rsync tests because rsync was not found' || {
test_expect_success 'fetch via rsync' '
git pack-refs &&
mkdir rsynced &&
- cd rsynced &&
- git init &&
- git fetch rsync://127.0.0.1$(pwd)/../.git master:refs/heads/master &&
- git gc --prune &&
- test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
- git fsck --full
+ (cd rsynced &&
+ git init --bare &&
+ git fetch "rsync:$(pwd)/../.git" master:refs/heads/master &&
+ git gc --prune &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full)
'
test_expect_success 'push via rsync' '
- mkdir ../rsynced2 &&
- (cd ../rsynced2 &&
+ mkdir rsynced2 &&
+ (cd rsynced2 &&
git init) &&
- git push rsync://127.0.0.1$(pwd)/../rsynced2/.git master &&
- cd ../rsynced2 &&
- git gc --prune &&
- test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
- git fsck --full
+ (cd rsynced &&
+ git push "rsync:$(pwd)/../rsynced2/.git" master) &&
+ (cd rsynced2 &&
+ git gc --prune &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full)
'
test_expect_success 'push via rsync' '
- cd .. &&
mkdir rsynced3 &&
(cd rsynced3 &&
git init) &&
- git push --all rsync://127.0.0.1$(pwd)/rsynced3/.git &&
- cd rsynced3 &&
- test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
- git fsck --full
+ git push --all "rsync:$(pwd)/rsynced3/.git" &&
+ (cd rsynced3 &&
+ test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
+ git fsck --full)
'
}
GIT_CONFIG=.gitmodules git config submodule.example.url git://example.com/init.git
'
+test_expect_success 'Prepare submodule add testing' '
+ submodurl=$(pwd)
+ (
+ mkdir addtest &&
+ cd addtest &&
+ git init
+ )
+'
+
+test_expect_success 'submodule add' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" submod &&
+ git submodule init
+ )
+'
+
+test_expect_success 'submodule add with ./ in path' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
+ git submodule init
+ )
+'
+
+test_expect_success 'submodule add with // in path' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" slashslashsubmod///frotz// &&
+ git submodule init
+ )
+'
+
+test_expect_success 'submodule add with /.. in path' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
+ git submodule init
+ )
+'
+
+test_expect_success 'submodule add with ./, /.. and // in path' '
+ (
+ cd addtest &&
+ git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
+ git submodule init
+ )
+'
+
test_expect_success 'status should fail for unmapped paths' '
if git submodule status
then
test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add master"
'
+test_expect_success 'in-reply-to but no threading' '
+ git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --in-reply-to="<in-reply-id@example.com>" \
+ --no-thread \
+ $patches |
+ grep "In-Reply-To: <in-reply-id@example.com>"
+'
+
test_done
fi
case "$test_failure" in
0)
- # We could:
- # cd .. && rm -fr 'trash directory'
- # but that means we forbid any tests that use their own
- # subdirectory from calling test_done without coming back
- # to where they started from.
- # The Makefile provided will clean this test area so
- # we will leave things as they are.
-
say_color pass "passed all $msg"
test -d "$remove_trash" &&
}
}
+static const char *rsync_url(const char *url)
+{
+ return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
+}
+
static struct ref *get_refs_via_rsync(struct transport *transport)
{
struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
die ("Could not make temporary directory");
temp_dir_len = temp_dir.len;
- strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, rsync_url(transport->url));
strbuf_addstr(&buf, "/refs");
memset(&rsync, 0, sizeof(rsync));
die ("Could not run rsync to get refs");
strbuf_reset(&buf);
- strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, rsync_url(transport->url));
strbuf_addstr(&buf, "/packed-refs");
args[2] = buf.buf;
const char *args[8];
int result;
- strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, rsync_url(transport->url));
strbuf_addstr(&buf, "/objects/");
memset(&rsync, 0, sizeof(rsync));
/* first push the objects */
- strbuf_addstr(&buf, transport->url);
+ strbuf_addstr(&buf, rsync_url(transport->url));
strbuf_addch(&buf, '/');
memset(&rsync, 0, sizeof(rsync));
args[i++] = NULL;
if (run_command(&rsync))
- return error("Could not push objects to %s", transport->url);
+ return error("Could not push objects to %s",
+ rsync_url(transport->url));
/* copy the refs to the temporary directory; they could be packed. */
if (!(flags & TRANSPORT_PUSH_FORCE))
args[i++] = "--ignore-existing";
args[i++] = temp_dir.buf;
- args[i++] = transport->url;
+ args[i++] = rsync_url(transport->url);
args[i++] = NULL;
if (run_command(&rsync))
- result = error("Could not push to %s", transport->url);
+ result = error("Could not push to %s",
+ rsync_url(transport->url));
if (remove_dir_recursively(&temp_dir, 0))
warning ("Could not remove temporary directory %s.",
ret->remote = remote;
ret->url = url;
- if (!prefixcmp(url, "rsync://")) {
+ if (!prefixcmp(url, "rsync:")) {
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
memcpy(new, ce, size);
new->next = NULL;
new->ce_flags = (new->ce_flags & ~clear) | set;
- add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|ADD_CACHE_SKIP_DFCHECK);
+ add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
}
/* Unlink the last component and attempt to remove leading
if (o->merge)
return call_unpack_fn(src, o);
- n += o->merge;
for (i = 0; i < n; i++)
- add_entry(o, src[i], 0, 0);
+ if (src[i] && src[i] != o->df_conflict_entry)
+ add_entry(o, src[i], 0, 0);
return 0;
}
static void report(const char *prefix, const char *err, va_list params)
{
- char msg[256];
+ char msg[1024];
vsnprintf(msg, sizeof(msg), err, params);
fprintf(stderr, "%s%s\n", prefix, msg);
}