mirror of
https://github.com/git/git.git
synced 2026-03-14 18:59:04 +01:00
Merge branch 'master' of git://repo.or.cz/alt-git
This commit is contained in:
@@ -37,10 +37,30 @@ Fixes since v1.5.4.3
|
||||
* "git revert" did not properly fail when attempting to run with a
|
||||
dirty index.
|
||||
|
||||
Also included are a handful documentation updates.
|
||||
* "git merge --no-commit --no-ff <other>" incorrectly made commits.
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
echo O=$(git describe maint)
|
||||
O=v1.5.4.3-32-g0f2d447
|
||||
git shortlog --no-merges $O..maint
|
||||
* "git merge --squash --no-ff <other>", which is a nonsense combination
|
||||
of options, was not rejected.
|
||||
|
||||
* "git ls-remote" and "git remote show" against an empty repository
|
||||
failed, instead of just giving an empty result (regression).
|
||||
|
||||
* "git fast-import" did not handle a renamed path whose name needs to be
|
||||
quoted, due to a bug in unquote_c_style() function.
|
||||
|
||||
* "git cvsexportcommit" was confused when multiple files with the same
|
||||
basename needed to be pushed out in the same commit.
|
||||
|
||||
* "git daemon" did not send early errors to syslog.
|
||||
|
||||
* "git log --merge" did not work well with --left-right option.
|
||||
|
||||
* "git svn" promprted for client cert password every time it accessed the
|
||||
server.
|
||||
|
||||
* The reset command in "git fast-import" data stream was documented to
|
||||
end with an optional LF, but it actually required one.
|
||||
|
||||
* "git svn dcommit/rebase" did not honor --rewrite-root option.
|
||||
|
||||
Also included are a handful documentation updates.
|
||||
|
||||
@@ -160,13 +160,9 @@ Fixes since v1.5.4
|
||||
All of the fixes in v1.5.4 maintenance series are included in
|
||||
this release, unless otherwise noted.
|
||||
|
||||
* "git-daemon" did not send early errors to syslog.
|
||||
|
||||
* "git-http-push" did not allow deletion of remote ref with the usual
|
||||
"push <remote> :<branch>" syntax.
|
||||
|
||||
* "git-log --merge" did not well work with --left-right option.
|
||||
|
||||
* "git-rebase --abort" did not go back to the right location if
|
||||
"git-reset" was run during the "git-rebase" session.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ git-am - Apply a series of patches from a mailbox
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-am' [--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]
|
||||
'git-am' [--signoff] [--keep] [--utf8 | --no-utf8]
|
||||
[--3way] [--interactive] [--binary]
|
||||
[--whitespace=<option>] [-C<n>] [-p<n>]
|
||||
<mbox>|<Maildir>...
|
||||
@@ -32,10 +32,6 @@ OPTIONS
|
||||
Add `Signed-off-by:` line to the commit message, using
|
||||
the committer identity of yourself.
|
||||
|
||||
-d=<dir>, --dotest=<dir>::
|
||||
Instead of `.dotest` directory, use <dir> as a working
|
||||
area to store extracted patches.
|
||||
|
||||
-k, --keep::
|
||||
Pass `-k` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]
|
||||
'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -45,6 +45,12 @@ OPTIONS
|
||||
Spend extra cycles to minimize the number of objects to be sent.
|
||||
Use it on slower connection.
|
||||
|
||||
\--include-tag::
|
||||
If the remote side supports it, annotated tags objects will
|
||||
be downloaded on the same connection as the other objects if
|
||||
the object the tag references is downloaded. The caller must
|
||||
otherwise determine the tags this option made available.
|
||||
|
||||
\--upload-pack=<git-upload-pack>::
|
||||
Use this to specify the path to 'git-upload-pack' on the
|
||||
remote side, if is not found on your $PATH.
|
||||
|
||||
@@ -12,12 +12,12 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
Use 'git mergetool' to run one of several merge utilities to resolve
|
||||
Use `git mergetool` to run one of several merge utilities to resolve
|
||||
merge conflicts. It is typically run after linkgit:git-merge[1].
|
||||
|
||||
If one or more <file> parameters are given, the merge tool program will
|
||||
be run to resolve differences on each file. If no <file> names are
|
||||
specified, 'git mergetool' will run the merge tool program on every file
|
||||
specified, `git mergetool` will run the merge tool program on every file
|
||||
with merge conflicts.
|
||||
|
||||
OPTIONS
|
||||
@@ -27,16 +27,38 @@ OPTIONS
|
||||
Valid merge tools are:
|
||||
kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
|
||||
+
|
||||
If a merge resolution program is not specified, 'git mergetool'
|
||||
will use the configuration variable merge.tool. If the
|
||||
configuration variable merge.tool is not set, 'git mergetool'
|
||||
If a merge resolution program is not specified, `git mergetool`
|
||||
will use the configuration variable `merge.tool`. If the
|
||||
configuration variable `merge.tool` is not set, `git mergetool`
|
||||
will pick a suitable default.
|
||||
+
|
||||
You can explicitly provide a full path to the tool by setting the
|
||||
configuration variable mergetool.<tool>.path. For example, you
|
||||
configuration variable `mergetool.<tool>.path`. For example, you
|
||||
can configure the absolute path to kdiff3 by setting
|
||||
mergetool.kdiff3.path. Otherwise, 'git mergetool' assumes the tool
|
||||
is available in PATH.
|
||||
`mergetool.kdiff3.path`. Otherwise, `git mergetool` assumes the
|
||||
tool is available in PATH.
|
||||
+
|
||||
Instead of running one of the known merge tool programs
|
||||
`git mergetool` can be customized to run an alternative program
|
||||
by specifying the command line to invoke in a configration
|
||||
variable `mergetool.<tool>.cmd`.
|
||||
+
|
||||
When `git mergetool` is invoked with this tool (either through the
|
||||
`-t` or `--tool` option or the `merge.tool` configuration
|
||||
variable) the configured command line will be invoked with `$BASE`
|
||||
set to the name of a temporary file containing the common base for
|
||||
the merge, if available; `$LOCAL` set to the name of a temporary
|
||||
file containing the contents of the file on the current branch;
|
||||
`$REMOTE` set to the name of a temporary file containing the
|
||||
contents of the file to be merged, and `$MERGED` set to the name
|
||||
of the file to which the merge tool should write the result of the
|
||||
merge resolution.
|
||||
+
|
||||
If the custom merge tool correctly indicates the success of a
|
||||
merge resolution with its exit code then the configuration
|
||||
variable `mergetool.<tool>.trustExitCode` can be set to `true`.
|
||||
Otherwise, `git mergetool` will prompt the user to indicate the
|
||||
success of the resolution after the custom tool has exited.
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
@@ -73,6 +73,11 @@ base-name::
|
||||
as if all refs under `$GIT_DIR/refs` are specified to be
|
||||
included.
|
||||
|
||||
--include-tag::
|
||||
Include unasked-for annotated tags if the object they
|
||||
reference was included in the resulting packfile. This
|
||||
can be useful to send new tags to native git clients.
|
||||
|
||||
--window=[N], --depth=[N]::
|
||||
These two options affect how the objects contained in
|
||||
the pack are stored using delta compression. The
|
||||
|
||||
@@ -325,7 +325,7 @@ The lines after the separator describe the options.
|
||||
Each line of options has this format:
|
||||
|
||||
------------
|
||||
<opt_spec><arg_spec>? SP+ help LF
|
||||
<opt_spec><flags>* SP+ help LF
|
||||
------------
|
||||
|
||||
`<opt_spec>`::
|
||||
@@ -334,10 +334,17 @@ Each line of options has this format:
|
||||
is necessary. `h,help`, `dry-run` and `f` are all three correct
|
||||
`<opt_spec>`.
|
||||
|
||||
`<arg_spec>`::
|
||||
an `<arg_spec>` tells the option parser if the option has an argument
|
||||
(`=`), an optional one (`?` though its use is discouraged) or none
|
||||
(no `<arg_spec>` in that case).
|
||||
`<flags>`::
|
||||
`<flags>` are of `*`, `=`, `?` or `!`.
|
||||
* Use `=` if the option takes an argument.
|
||||
|
||||
* Use `?` to mean that the option is optional (though its use is discouraged).
|
||||
|
||||
* Use `*` to mean that this option should not be listed in the usage
|
||||
generated for the `-h` argument. It's shown for `--help-all` as
|
||||
documented in linkgit:gitcli[5].
|
||||
|
||||
* Use `!` to not make the corresponding negated long option available.
|
||||
|
||||
The remainder of the line, after stripping the spaces, is used
|
||||
as the help associated to the option.
|
||||
|
||||
@@ -18,8 +18,9 @@ COMMANDS
|
||||
--------
|
||||
add::
|
||||
Add the given repository as a submodule at the given path
|
||||
to the changeset to be committed next. In particular, the
|
||||
repository is cloned at the specified path, added to the
|
||||
to the changeset to be committed next. If path is a valid
|
||||
repository within the project, it is added as is. Otherwise,
|
||||
repository is cloned at the specified path. path is added to the
|
||||
changeset and registered in .gitmodules. If no path is
|
||||
specified, the path is deduced from the repository specification.
|
||||
If the repository url begins with ./ or ../, it is stored as
|
||||
|
||||
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.5.4.3/git.html[documentation for release 1.5.4.3]
|
||||
* link:v1.5.4.4/git.html[documentation for release 1.5.4.4]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.5.4.4.txt[1.5.4.4],
|
||||
link:RelNotes-1.5.4.3.txt[1.5.4.3],
|
||||
link:RelNotes-1.5.4.2.txt[1.5.4.2],
|
||||
link:RelNotes-1.5.4.1.txt[1.5.4.1],
|
||||
|
||||
8
Makefile
8
Makefile
@@ -3,6 +3,10 @@ all::
|
||||
|
||||
# Define V=1 to have a more verbose compile.
|
||||
#
|
||||
# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
|
||||
# or vsnprintf() return -1 instead of number of characters which would
|
||||
# have been written to the final string if enough space had been available.
|
||||
#
|
||||
# Define FREAD_READS_DIRECTORIES if your are on a system which succeeds
|
||||
# when attempting to read from an fopen'ed directory.
|
||||
#
|
||||
@@ -663,6 +667,10 @@ endif
|
||||
ifdef NO_C99_FORMAT
|
||||
BASIC_CFLAGS += -DNO_C99_FORMAT
|
||||
endif
|
||||
ifdef SNPRINTF_RETURNS_BOGUS
|
||||
COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS
|
||||
COMPAT_OBJS += compat/snprintf.o
|
||||
endif
|
||||
ifdef FREAD_READS_DIRECTORIES
|
||||
COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES
|
||||
COMPAT_OBJS += compat/fopen.o
|
||||
|
||||
@@ -228,18 +228,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (*argv) {
|
||||
/* Was there an invalid path? */
|
||||
if (pathspec) {
|
||||
int num;
|
||||
for (num = 0; pathspec[num]; num++)
|
||||
; /* just counting */
|
||||
if (argc != num)
|
||||
exit(1); /* error message already given */
|
||||
} else
|
||||
exit(1); /* error message already given */
|
||||
}
|
||||
|
||||
fill_directory(&dir, pathspec, ignored_too);
|
||||
|
||||
if (show_only) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "cache.h"
|
||||
#include "dir.h"
|
||||
#include "parse-options.h"
|
||||
#include "quote.h"
|
||||
|
||||
static int force = -1; /* unset */
|
||||
|
||||
@@ -34,7 +35,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
struct dir_struct dir;
|
||||
const char *path, *base;
|
||||
static const char **pathspec;
|
||||
int prefix_offset = 0;
|
||||
struct strbuf buf;
|
||||
const char *qname;
|
||||
char *seen = NULL;
|
||||
struct option options[] = {
|
||||
OPT__QUIET(&quiet),
|
||||
@@ -56,6 +58,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_clean_usage, 0);
|
||||
|
||||
strbuf_init(&buf, 0);
|
||||
memset(&dir, 0, sizeof(dir));
|
||||
if (ignored_only)
|
||||
dir.show_ignored = 1;
|
||||
@@ -72,8 +75,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
if (!ignored)
|
||||
setup_standard_excludes(&dir);
|
||||
|
||||
if (prefix)
|
||||
prefix_offset = strlen(prefix);
|
||||
pathspec = get_pathspec(prefix, argv);
|
||||
read_cache();
|
||||
|
||||
@@ -134,39 +135,34 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
strbuf_addstr(&directory, ent->name);
|
||||
qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
|
||||
if (show_only && (remove_directories || matches)) {
|
||||
printf("Would remove %s\n",
|
||||
directory.buf + prefix_offset);
|
||||
printf("Would remove %s\n", qname);
|
||||
} else if (remove_directories || matches) {
|
||||
if (!quiet)
|
||||
printf("Removing %s\n",
|
||||
directory.buf + prefix_offset);
|
||||
printf("Removing %s\n", qname);
|
||||
if (remove_dir_recursively(&directory, 0) != 0) {
|
||||
warning("failed to remove '%s'",
|
||||
directory.buf + prefix_offset);
|
||||
warning("failed to remove '%s'", qname);
|
||||
errors++;
|
||||
}
|
||||
} else if (show_only) {
|
||||
printf("Would not remove %s\n",
|
||||
directory.buf + prefix_offset);
|
||||
printf("Would not remove %s\n", qname);
|
||||
} else {
|
||||
printf("Not removing %s\n",
|
||||
directory.buf + prefix_offset);
|
||||
printf("Not removing %s\n", qname);
|
||||
}
|
||||
strbuf_reset(&directory);
|
||||
} else {
|
||||
if (pathspec && !matches)
|
||||
continue;
|
||||
qname = quote_path_relative(ent->name, -1, &buf, prefix);
|
||||
if (show_only) {
|
||||
printf("Would remove %s\n",
|
||||
ent->name + prefix_offset);
|
||||
printf("Would remove %s\n", qname);
|
||||
continue;
|
||||
} else if (!quiet) {
|
||||
printf("Removing %s\n",
|
||||
ent->name + prefix_offset);
|
||||
printf("Removing %s\n", qname);
|
||||
}
|
||||
if (unlink(ent->name) != 0) {
|
||||
warning("failed to remove '%s'", ent->name);
|
||||
warning("failed to remove '%s'", qname);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ static int longformat;
|
||||
static int abbrev = DEFAULT_ABBREV;
|
||||
static int max_candidates = 10;
|
||||
const char *pattern = NULL;
|
||||
static int always;
|
||||
|
||||
struct commit_name {
|
||||
struct tag *tag;
|
||||
@@ -257,8 +258,14 @@ static void describe(const char *arg, int last_one)
|
||||
}
|
||||
}
|
||||
|
||||
if (!match_cnt)
|
||||
die("cannot describe '%s'", sha1_to_hex(cmit->object.sha1));
|
||||
if (!match_cnt) {
|
||||
const unsigned char *sha1 = cmit->object.sha1;
|
||||
if (always) {
|
||||
printf("%s\n", find_unique_abbrev(sha1, abbrev));
|
||||
return;
|
||||
}
|
||||
die("cannot describe '%s'", sha1_to_hex(sha1));
|
||||
}
|
||||
|
||||
qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt);
|
||||
|
||||
@@ -311,6 +318,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
|
||||
"consider <n> most recent tags (default: 10)"),
|
||||
OPT_STRING(0, "match", &pattern, "pattern",
|
||||
"only consider tags matching <pattern>"),
|
||||
OPT_BOOLEAN(0, "always", &always,
|
||||
"show abbreviated commit object as fallback"),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
@@ -326,11 +335,13 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
|
||||
die("--long is incompatible with --abbrev=0");
|
||||
|
||||
if (contains) {
|
||||
const char **args = xmalloc((6 + argc) * sizeof(char*));
|
||||
const char **args = xmalloc((7 + argc) * sizeof(char*));
|
||||
int i = 0;
|
||||
args[i++] = "name-rev";
|
||||
args[i++] = "--name-only";
|
||||
args[i++] = "--no-undefined";
|
||||
if (always)
|
||||
args[i++] = "--always";
|
||||
if (!all) {
|
||||
args[i++] = "--tags";
|
||||
if (pattern) {
|
||||
|
||||
@@ -18,7 +18,7 @@ static struct fetch_pack_args args = {
|
||||
};
|
||||
|
||||
static const char fetch_pack_usage[] =
|
||||
"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
|
||||
"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
|
||||
|
||||
#define COMPLETE (1U << 0)
|
||||
#define COMMON (1U << 1)
|
||||
@@ -176,13 +176,14 @@ static int find_common(int fd[2], unsigned char *result_sha1,
|
||||
}
|
||||
|
||||
if (!fetching)
|
||||
packet_write(fd[1], "want %s%s%s%s%s%s%s\n",
|
||||
packet_write(fd[1], "want %s%s%s%s%s%s%s%s\n",
|
||||
sha1_to_hex(remote),
|
||||
(multi_ack ? " multi_ack" : ""),
|
||||
(use_sideband == 2 ? " side-band-64k" : ""),
|
||||
(use_sideband == 1 ? " side-band" : ""),
|
||||
(args.use_thin_pack ? " thin-pack" : ""),
|
||||
(args.no_progress ? " no-progress" : ""),
|
||||
(args.include_tag ? " include-tag" : ""),
|
||||
" ofs-delta");
|
||||
else
|
||||
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
|
||||
@@ -683,6 +684,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
|
||||
args.use_thin_pack = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--include-tag", arg)) {
|
||||
args.include_tag = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--all", arg)) {
|
||||
args.fetch_all = 1;
|
||||
continue;
|
||||
|
||||
@@ -101,6 +101,10 @@ static void add_merge_config(struct ref **head,
|
||||
}
|
||||
}
|
||||
|
||||
static void find_non_local_tags(struct transport *transport,
|
||||
struct ref **head,
|
||||
struct ref ***tail);
|
||||
|
||||
static struct ref *get_ref_map(struct transport *transport,
|
||||
struct refspec *refs, int ref_count, int tags,
|
||||
int *autotags)
|
||||
@@ -157,8 +161,11 @@ static struct ref *get_ref_map(struct transport *transport,
|
||||
if (!ref_map)
|
||||
die("Couldn't find remote ref HEAD");
|
||||
ref_map->merge = 1;
|
||||
tail = &ref_map->next;
|
||||
}
|
||||
}
|
||||
if (tags == TAGS_DEFAULT && *autotags)
|
||||
find_non_local_tags(transport, &ref_map, &tail);
|
||||
ref_remove_duplicates(ref_map);
|
||||
|
||||
return ref_map;
|
||||
@@ -452,18 +459,28 @@ static int add_existing(const char *refname, const unsigned char *sha1,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ref *find_non_local_tags(struct transport *transport,
|
||||
struct ref *fetch_map)
|
||||
static int will_fetch(struct ref **head, const unsigned char *sha1)
|
||||
{
|
||||
static struct path_list existing_refs = { NULL, 0, 0, 0 };
|
||||
struct ref *rm = *head;
|
||||
while (rm) {
|
||||
if (!hashcmp(rm->old_sha1, sha1))
|
||||
return 1;
|
||||
rm = rm->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void find_non_local_tags(struct transport *transport,
|
||||
struct ref **head,
|
||||
struct ref ***tail)
|
||||
{
|
||||
struct path_list existing_refs = { NULL, 0, 0, 0 };
|
||||
struct path_list new_refs = { NULL, 0, 0, 1 };
|
||||
char *ref_name;
|
||||
int ref_name_len;
|
||||
const unsigned char *ref_sha1;
|
||||
const struct ref *tag_ref;
|
||||
struct ref *rm = NULL;
|
||||
struct ref *ref_map = NULL;
|
||||
struct ref **tail = &ref_map;
|
||||
const struct ref *ref;
|
||||
|
||||
for_each_ref(add_existing, &existing_refs);
|
||||
@@ -489,7 +506,8 @@ static struct ref *find_non_local_tags(struct transport *transport,
|
||||
|
||||
if (!path_list_has_path(&existing_refs, ref_name) &&
|
||||
!path_list_has_path(&new_refs, ref_name) &&
|
||||
has_sha1_file(ref->old_sha1)) {
|
||||
(has_sha1_file(ref->old_sha1) ||
|
||||
will_fetch(head, ref->old_sha1))) {
|
||||
path_list_insert(ref_name, &new_refs);
|
||||
|
||||
rm = alloc_ref(strlen(ref_name) + 1);
|
||||
@@ -498,19 +516,19 @@ static struct ref *find_non_local_tags(struct transport *transport,
|
||||
strcpy(rm->peer_ref->name, ref_name);
|
||||
hashcpy(rm->old_sha1, ref_sha1);
|
||||
|
||||
*tail = rm;
|
||||
tail = &rm->next;
|
||||
**tail = rm;
|
||||
*tail = &rm->next;
|
||||
}
|
||||
free(ref_name);
|
||||
}
|
||||
|
||||
return ref_map;
|
||||
path_list_clear(&existing_refs, 0);
|
||||
path_list_clear(&new_refs, 0);
|
||||
}
|
||||
|
||||
static int do_fetch(struct transport *transport,
|
||||
struct refspec *refs, int ref_count)
|
||||
{
|
||||
struct ref *ref_map, *fetch_map;
|
||||
struct ref *ref_map;
|
||||
struct ref *rm;
|
||||
int autotags = (transport->remote->fetch_tags == 1);
|
||||
if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET)
|
||||
@@ -537,26 +555,28 @@ static int do_fetch(struct transport *transport,
|
||||
read_ref(rm->peer_ref->name, rm->peer_ref->old_sha1);
|
||||
}
|
||||
|
||||
if (tags == TAGS_DEFAULT && autotags)
|
||||
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
|
||||
if (fetch_refs(transport, ref_map)) {
|
||||
free_refs(ref_map);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fetch_map = ref_map;
|
||||
free_refs(ref_map);
|
||||
|
||||
/* if neither --no-tags nor --tags was specified, do automated tag
|
||||
* following ... */
|
||||
if (tags == TAGS_DEFAULT && autotags) {
|
||||
ref_map = find_non_local_tags(transport, fetch_map);
|
||||
struct ref **tail = &ref_map;
|
||||
ref_map = NULL;
|
||||
find_non_local_tags(transport, &ref_map, &tail);
|
||||
if (ref_map) {
|
||||
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
|
||||
transport_set_option(transport, TRANS_OPT_DEPTH, "0");
|
||||
fetch_refs(transport, ref_map);
|
||||
}
|
||||
free_refs(ref_map);
|
||||
}
|
||||
|
||||
free_refs(fetch_map);
|
||||
|
||||
transport_disconnect(transport);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -574,17 +574,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
pathspec = get_pathspec(prefix, argv + i);
|
||||
|
||||
/* Verify that the pathspec matches the prefix */
|
||||
if (pathspec) {
|
||||
if (argc != i) {
|
||||
int cnt;
|
||||
for (cnt = 0; pathspec[cnt]; cnt++)
|
||||
;
|
||||
if (cnt != (argc - i))
|
||||
exit(1); /* error message already given */
|
||||
}
|
||||
if (pathspec)
|
||||
prefix = verify_pathspec(prefix);
|
||||
} else if (argc != i)
|
||||
exit(1); /* error message already given */
|
||||
|
||||
/* Treat unmatching pathspec elements as errors */
|
||||
if (pathspec && error_unmatch) {
|
||||
|
||||
@@ -19,7 +19,6 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
|
||||
int count, int base_name)
|
||||
{
|
||||
int i;
|
||||
int len = prefix ? strlen(prefix) : 0;
|
||||
const char **result = xmalloc((count + 1) * sizeof(const char *));
|
||||
memcpy(result, pathspec, count * sizeof(const char *));
|
||||
result[count] = NULL;
|
||||
@@ -33,11 +32,8 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
|
||||
if (last_slash)
|
||||
result[i] = last_slash + 1;
|
||||
}
|
||||
result[i] = prefix_path(prefix, len, result[i]);
|
||||
if (!result[i])
|
||||
exit(1); /* error already given */
|
||||
}
|
||||
return result;
|
||||
return get_pathspec(prefix, result);
|
||||
}
|
||||
|
||||
static void show_list(const char *label, struct path_list *list)
|
||||
|
||||
@@ -125,7 +125,7 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void
|
||||
}
|
||||
|
||||
/* returns a static buffer */
|
||||
static const char *get_rev_name(struct object *o)
|
||||
static const char *get_rev_name(const struct object *o)
|
||||
{
|
||||
static char buffer[1024];
|
||||
struct rev_name *n;
|
||||
@@ -151,6 +151,26 @@ static const char *get_rev_name(struct object *o)
|
||||
}
|
||||
}
|
||||
|
||||
static void show_name(const struct object *obj,
|
||||
const char *caller_name,
|
||||
int always, int allow_undefined, int name_only)
|
||||
{
|
||||
const char *name;
|
||||
const unsigned char *sha1 = obj->sha1;
|
||||
|
||||
if (!name_only)
|
||||
printf("%s ", caller_name ? caller_name : sha1_to_hex(sha1));
|
||||
name = get_rev_name(obj);
|
||||
if (name)
|
||||
printf("%s\n", name);
|
||||
else if (allow_undefined)
|
||||
printf("undefined\n");
|
||||
else if (always)
|
||||
printf("%s\n", find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
||||
else
|
||||
die("cannot describe '%s'", sha1_to_hex(sha1));
|
||||
}
|
||||
|
||||
static char const * const name_rev_usage[] = {
|
||||
"git-name-rev [options] ( --all | --stdin | <commit>... )",
|
||||
NULL
|
||||
@@ -159,7 +179,7 @@ static char const * const name_rev_usage[] = {
|
||||
int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct object_array revs = { 0, 0, NULL };
|
||||
int all = 0, transform_stdin = 0, allow_undefined = 1;
|
||||
int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0;
|
||||
struct name_ref_data data = { 0, 0, NULL };
|
||||
struct option opts[] = {
|
||||
OPT_BOOLEAN(0, "name-only", &data.name_only, "print only names (no SHA-1)"),
|
||||
@@ -170,6 +190,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
||||
OPT_BOOLEAN(0, "all", &all, "list all commits reachable from all refs"),
|
||||
OPT_BOOLEAN(0, "stdin", &transform_stdin, "read from stdin"),
|
||||
OPT_BOOLEAN(0, "undefined", &allow_undefined, "allow to print `undefined` names"),
|
||||
OPT_BOOLEAN(0, "always", &always,
|
||||
"show abbreviated commit object as fallback"),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
@@ -258,35 +280,14 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
||||
int i, max;
|
||||
|
||||
max = get_max_object_index();
|
||||
for (i = 0; i < max; i++) {
|
||||
struct object * obj = get_indexed_object(i);
|
||||
const char *name;
|
||||
if (!obj)
|
||||
continue;
|
||||
if (!data.name_only)
|
||||
printf("%s ", sha1_to_hex(obj->sha1));
|
||||
name = get_rev_name(obj);
|
||||
if (name)
|
||||
printf("%s\n", name);
|
||||
else if (allow_undefined)
|
||||
printf("undefined\n");
|
||||
else
|
||||
die("cannot describe '%s'", sha1_to_hex(obj->sha1));
|
||||
}
|
||||
for (i = 0; i < max; i++)
|
||||
show_name(get_indexed_object(i), NULL,
|
||||
always, allow_undefined, data.name_only);
|
||||
} else {
|
||||
int i;
|
||||
for (i = 0; i < revs.nr; i++) {
|
||||
const char *name;
|
||||
if (!data.name_only)
|
||||
printf("%s ", revs.objects[i].name);
|
||||
name = get_rev_name(revs.objects[i].item);
|
||||
if (name)
|
||||
printf("%s\n", name);
|
||||
else if (allow_undefined)
|
||||
printf("undefined\n");
|
||||
else
|
||||
die("cannot describe '%s'", sha1_to_hex(revs.objects[i].item->sha1));
|
||||
}
|
||||
for (i = 0; i < revs.nr; i++)
|
||||
show_name(revs.objects[i].item, revs.objects[i].name,
|
||||
always, allow_undefined, data.name_only);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "revision.h"
|
||||
#include "list-objects.h"
|
||||
#include "progress.h"
|
||||
#include "refs.h"
|
||||
|
||||
#ifdef THREADED_DELTA_SEARCH
|
||||
#include "thread-utils.h"
|
||||
@@ -27,7 +28,8 @@ git-pack-objects [{ -q | --progress | --all-progress }] \n\
|
||||
[--window=N] [--window-memory=N] [--depth=N] \n\
|
||||
[--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\
|
||||
[--threads=N] [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\
|
||||
[--stdout | base-name] [--keep-unreachable] [<ref-list | <object-list]";
|
||||
[--stdout | base-name] [--include-tag] [--keep-unreachable] \n\
|
||||
[<ref-list | <object-list]";
|
||||
|
||||
struct object_entry {
|
||||
struct pack_idx_entry idx;
|
||||
@@ -63,7 +65,7 @@ static struct pack_idx_entry **written_list;
|
||||
static uint32_t nr_objects, nr_alloc, nr_result, nr_written;
|
||||
|
||||
static int non_empty;
|
||||
static int no_reuse_delta, no_reuse_object, keep_unreachable;
|
||||
static int no_reuse_delta, no_reuse_object, keep_unreachable, include_tag;
|
||||
static int local;
|
||||
static int incremental;
|
||||
static int allow_ofs_delta;
|
||||
@@ -1630,6 +1632,18 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
|
||||
#define ll_find_deltas(l, s, w, d, p) find_deltas(l, &s, w, d, p)
|
||||
#endif
|
||||
|
||||
static int add_ref_tag(const char *path, const unsigned char *sha1, int flag, void *cb_data)
|
||||
{
|
||||
unsigned char peeled[20];
|
||||
|
||||
if (!prefixcmp(path, "refs/tags/") && /* is a tag? */
|
||||
!peel_ref(path, peeled) && /* peelable? */
|
||||
!is_null_sha1(peeled) && /* annotated tag? */
|
||||
locate_object_entry(peeled)) /* object packed? */
|
||||
add_object_entry(sha1, OBJ_TAG, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prepare_pack(int window, int depth)
|
||||
{
|
||||
struct object_entry **delta_list;
|
||||
@@ -2033,6 +2047,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
||||
keep_unreachable = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--include-tag", arg)) {
|
||||
include_tag = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--unpacked", arg) ||
|
||||
!prefixcmp(arg, "--unpacked=") ||
|
||||
!strcmp("--reflog", arg) ||
|
||||
@@ -2109,6 +2127,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
||||
rp_av[rp_ac] = NULL;
|
||||
get_object_list(rp_ac, rp_av);
|
||||
}
|
||||
if (include_tag && nr_result)
|
||||
for_each_ref(add_ref_tag, NULL);
|
||||
stop_progress(&progress_state);
|
||||
|
||||
if (non_empty && !nr_result)
|
||||
|
||||
@@ -17,9 +17,13 @@
|
||||
#include "diffcore.h"
|
||||
#include "tree.h"
|
||||
#include "branch.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char builtin_reset_usage[] =
|
||||
"git-reset [--mixed | --soft | --hard] [-q] [<commit-ish>] [ [--] <paths>...]";
|
||||
static const char * const git_reset_usage[] = {
|
||||
"git-reset [--mixed | --soft | --hard] [-q] [<commit>]",
|
||||
"git-reset [--mixed] <commit> [--] <paths>...",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *args_to_str(const char **argv)
|
||||
{
|
||||
@@ -165,40 +169,31 @@ static const char *reset_type_names[] = { "mixed", "soft", "hard", NULL };
|
||||
|
||||
int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i = 1, reset_type = NONE, update_ref_status = 0, quiet = 0;
|
||||
int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0;
|
||||
const char *rev = "HEAD";
|
||||
unsigned char sha1[20], *orig = NULL, sha1_orig[20],
|
||||
*old_orig = NULL, sha1_old_orig[20];
|
||||
struct commit *commit;
|
||||
char *reflog_action, msg[1024];
|
||||
const struct option options[] = {
|
||||
OPT_SET_INT(0, "mixed", &reset_type,
|
||||
"reset HEAD and index", MIXED),
|
||||
OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT),
|
||||
OPT_SET_INT(0, "hard", &reset_type,
|
||||
"reset HEAD, index and working tree", HARD),
|
||||
OPT_BOOLEAN('q', NULL, &quiet,
|
||||
"disable showing new HEAD in hard reset"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config);
|
||||
|
||||
argc = parse_options(argc, argv, options, git_reset_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
reflog_action = args_to_str(argv);
|
||||
setenv("GIT_REFLOG_ACTION", reflog_action, 0);
|
||||
|
||||
while (i < argc) {
|
||||
if (!strcmp(argv[i], "--mixed")) {
|
||||
reset_type = MIXED;
|
||||
i++;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--soft")) {
|
||||
reset_type = SOFT;
|
||||
i++;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--hard")) {
|
||||
reset_type = HARD;
|
||||
i++;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-q")) {
|
||||
quiet = 1;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < argc && argv[i][0] != '-')
|
||||
if (i < argc && strcmp(argv[i], "--"))
|
||||
rev = argv[i++];
|
||||
|
||||
if (get_sha1(rev, sha1))
|
||||
@@ -211,8 +206,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
|
||||
if (i < argc && !strcmp(argv[i], "--"))
|
||||
i++;
|
||||
else if (i < argc && argv[i][0] == '-')
|
||||
usage(builtin_reset_usage);
|
||||
|
||||
/* git reset tree [--] paths... can be used to
|
||||
* load chosen paths from the tree into the index without
|
||||
|
||||
@@ -322,18 +322,24 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
|
||||
o->type = OPTION_CALLBACK;
|
||||
o->help = xstrdup(skipspaces(s));
|
||||
o->value = &parsed;
|
||||
o->flags = PARSE_OPT_NOARG;
|
||||
o->callback = &parseopt_dump;
|
||||
switch (s[-1]) {
|
||||
case '=':
|
||||
s--;
|
||||
break;
|
||||
case '?':
|
||||
o->flags = PARSE_OPT_OPTARG;
|
||||
s--;
|
||||
break;
|
||||
default:
|
||||
o->flags = PARSE_OPT_NOARG;
|
||||
break;
|
||||
while (s > sb.buf && strchr("*=?!", s[-1])) {
|
||||
switch (*--s) {
|
||||
case '=':
|
||||
o->flags &= ~PARSE_OPT_NOARG;
|
||||
break;
|
||||
case '?':
|
||||
o->flags &= ~PARSE_OPT_NOARG;
|
||||
o->flags |= PARSE_OPT_OPTARG;
|
||||
break;
|
||||
case '!':
|
||||
o->flags |= PARSE_OPT_NONEG;
|
||||
break;
|
||||
case '*':
|
||||
o->flags |= PARSE_OPT_HIDDEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s - sb.buf == 1) /* short option only */
|
||||
|
||||
@@ -70,11 +70,12 @@ static void insert_one_record(struct shortlog *log,
|
||||
else
|
||||
free(buffer);
|
||||
|
||||
/* Skip any leading whitespace, including any blank lines. */
|
||||
while (*oneline && isspace(*oneline))
|
||||
oneline++;
|
||||
eol = strchr(oneline, '\n');
|
||||
if (!eol)
|
||||
eol = oneline + strlen(oneline);
|
||||
while (*oneline && isspace(*oneline) && *oneline != '\n')
|
||||
oneline++;
|
||||
if (!prefixcmp(oneline, "[PATCH")) {
|
||||
char *eob = strchr(oneline, ']');
|
||||
if (eob && (!eol || eob < eol))
|
||||
|
||||
40
compat/snprintf.c
Normal file
40
compat/snprintf.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "../git-compat-util.h"
|
||||
|
||||
#undef vsnprintf
|
||||
int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
|
||||
{
|
||||
char *s;
|
||||
int ret;
|
||||
|
||||
ret = vsnprintf(str, maxsize, format, ap);
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
|
||||
s = NULL;
|
||||
if (maxsize < 128)
|
||||
maxsize = 128;
|
||||
|
||||
while (ret == -1) {
|
||||
maxsize *= 4;
|
||||
str = realloc(s, maxsize);
|
||||
if (! str)
|
||||
break;
|
||||
s = str;
|
||||
ret = vsnprintf(str, maxsize, format, ap);
|
||||
}
|
||||
free(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int git_snprintf(char *str, size_t maxsize, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = git_vsnprintf(str, maxsize, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -46,3 +46,4 @@ NO_MKDTEMP=@NO_MKDTEMP@
|
||||
NO_ICONV=@NO_ICONV@
|
||||
OLD_ICONV=@OLD_ICONV@
|
||||
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
|
||||
SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
|
||||
|
||||
34
configure.ac
34
configure.ac
@@ -326,6 +326,40 @@ else
|
||||
NO_C99_FORMAT=
|
||||
fi
|
||||
AC_SUBST(NO_C99_FORMAT)
|
||||
#
|
||||
# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
|
||||
# or vsnprintf() return -1 instead of number of characters which would
|
||||
# have been written to the final string if enough space had been available.
|
||||
AC_CACHE_CHECK([whether snprintf() and/or vsnprintf() return bogus value],
|
||||
[ac_cv_snprintf_returns_bogus],
|
||||
[
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
|
||||
#include "stdarg.h"
|
||||
|
||||
int test_vsnprintf(char *str, size_t maxsize, const char *format, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
ret = vsnprintf(str, maxsize, format, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}],
|
||||
[[char buf[6];
|
||||
if (test_vsnprintf(buf, 3, "%s", "12345") != 5
|
||||
|| strcmp(buf, "12")) return 1;
|
||||
if (snprintf(buf, 3, "%s", "12345") != 5
|
||||
|| strcmp(buf, "12")) return 1]])],
|
||||
[ac_cv_snprintf_returns_bogus=no],
|
||||
[ac_cv_snprintf_returns_bogus=yes])
|
||||
])
|
||||
if test $ac_cv_snprintf_returns_bogus = yes; then
|
||||
SNPRINTF_RETURNS_BOGUS=UnfortunatelyYes
|
||||
else
|
||||
SNPRINTF_RETURNS_BOGUS=
|
||||
fi
|
||||
AC_SUBST(SNPRINTF_RETURNS_BOGUS)
|
||||
|
||||
|
||||
## Checks for library functions.
|
||||
|
||||
@@ -70,7 +70,15 @@ __git_ps1 ()
|
||||
local b
|
||||
if [ -d "$g/../.dotest" ]
|
||||
then
|
||||
r="|AM/REBASE"
|
||||
if test -f "$g/../.dotest/rebasing"
|
||||
then
|
||||
r="|REBASE"
|
||||
elif test -f "$g/../.dotest/applying"
|
||||
then
|
||||
r="|AM"
|
||||
else
|
||||
r="|AM/REBASE"
|
||||
fi
|
||||
b="$(git symbolic-ref HEAD 2>/dev/null)"
|
||||
elif [ -f "$g/.dotest-merge/interactive" ]
|
||||
then
|
||||
|
||||
@@ -2291,7 +2291,8 @@ static void cmd_reset_branch(void)
|
||||
else
|
||||
b = new_branch(sp);
|
||||
read_next_command();
|
||||
if (!cmd_from(b) && command_buf.len > 0)
|
||||
cmd_from(b);
|
||||
if (command_buf.len > 0)
|
||||
unread_command_buf = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ struct fetch_pack_args
|
||||
use_thin_pack:1,
|
||||
fetch_all:1,
|
||||
verbose:1,
|
||||
no_progress:1;
|
||||
no_progress:1,
|
||||
include_tag:1;
|
||||
};
|
||||
|
||||
struct ref *fetch_pack(struct fetch_pack_args *args,
|
||||
|
||||
44
git-am.sh
44
git-am.sh
@@ -9,7 +9,7 @@ git-am [options] <mbox>|<Maildir>...
|
||||
git-am [options] --resolved
|
||||
git-am [options] --skip
|
||||
--
|
||||
d,dotest= use <dir> and not .dotest
|
||||
d,dotest= (removed -- do not use)
|
||||
i,interactive run interactively
|
||||
b,binary pass --allo-binary-replacement to git-apply
|
||||
3,3way allow fall back on 3way merging if needed
|
||||
@@ -21,9 +21,11 @@ C= pass it through git-apply
|
||||
p= pass it through git-apply
|
||||
resolvemsg= override error message when patch failure occurs
|
||||
r,resolved to be used after a patch failure
|
||||
skip skip the current patch"
|
||||
skip skip the current patch
|
||||
rebasing (internal use for git-rebase)"
|
||||
|
||||
. git-sh-setup
|
||||
prefix=$(git rev-parse --show-prefix)
|
||||
set_reflog_action am
|
||||
require_work_tree
|
||||
cd_to_toplevel
|
||||
@@ -49,10 +51,6 @@ stop_here_user_resolve () {
|
||||
then
|
||||
cmdline="$cmdline -3"
|
||||
fi
|
||||
if test '.dotest' != "$dotest"
|
||||
then
|
||||
cmdline="$cmdline -d=$dotest"
|
||||
fi
|
||||
echo "When you have resolved this problem run \"$cmdline --resolved\"."
|
||||
echo "If you would prefer to skip this patch, instead run \"$cmdline --skip\"."
|
||||
|
||||
@@ -124,7 +122,8 @@ reread_subject () {
|
||||
}
|
||||
|
||||
prec=4
|
||||
dotest=.dotest sign= utf8=t keep= skip= interactive= resolved= binary=
|
||||
dotest=".dotest"
|
||||
sign= utf8=t keep= skip= interactive= resolved= binary= rebasing=
|
||||
resolvemsg= resume=
|
||||
git_apply_opt=
|
||||
|
||||
@@ -149,8 +148,11 @@ do
|
||||
resolved=t ;;
|
||||
--skip)
|
||||
skip=t ;;
|
||||
--rebasing)
|
||||
rebasing=t threeway=t keep=t binary=t ;;
|
||||
-d|--dotest)
|
||||
shift; dotest=$1;;
|
||||
die "-d option is no longer supported. Do not use."
|
||||
;;
|
||||
--resolvemsg)
|
||||
shift; resolvemsg=$1 ;;
|
||||
--whitespace)
|
||||
@@ -186,7 +188,7 @@ then
|
||||
0,)
|
||||
# No file input but without resume parameters; catch
|
||||
# user error to feed us a patch from standard input
|
||||
# when there is already .dotest. This is somewhat
|
||||
# when there is already $dotest. This is somewhat
|
||||
# unreliable -- stdin could be /dev/null for example
|
||||
# and the caller did not intend to feed us a patch but
|
||||
# wanted to continue unattended.
|
||||
@@ -206,6 +208,24 @@ else
|
||||
# Start afresh.
|
||||
mkdir -p "$dotest" || exit
|
||||
|
||||
if test -n "$prefix" && test $# != 0
|
||||
then
|
||||
first=t
|
||||
for arg
|
||||
do
|
||||
test -n "$first" && {
|
||||
set x
|
||||
first=
|
||||
}
|
||||
case "$arg" in
|
||||
/*)
|
||||
set "$@" "$arg" ;;
|
||||
*)
|
||||
set "$@" "$prefix$arg" ;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
fi
|
||||
git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" || {
|
||||
rm -fr "$dotest"
|
||||
exit 1
|
||||
@@ -220,6 +240,12 @@ else
|
||||
echo "$utf8" >"$dotest/utf8"
|
||||
echo "$keep" >"$dotest/keep"
|
||||
echo 1 >"$dotest/next"
|
||||
if test -n "$rebasing"
|
||||
then
|
||||
: >"$dotest/rebasing"
|
||||
else
|
||||
: >"$dotest/applying"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$resolved" in
|
||||
|
||||
@@ -219,6 +219,15 @@ void *gitmemmem(const void *haystack, size_t haystacklen,
|
||||
extern FILE *git_fopen(const char*, const char*);
|
||||
#endif
|
||||
|
||||
#ifdef SNPRINTF_RETURNS_BOGUS
|
||||
#define snprintf git_snprintf
|
||||
extern int git_snprintf(char *str, size_t maxsize,
|
||||
const char *format, ...);
|
||||
#define vsnprintf git_vsnprintf
|
||||
extern int git_vsnprintf(char *str, size_t maxsize,
|
||||
const char *format, va_list ap);
|
||||
#endif
|
||||
|
||||
#ifdef __GLIBC_PREREQ
|
||||
#if __GLIBC_PREREQ(2, 1)
|
||||
#define HAVE_STRCHRNUL
|
||||
|
||||
@@ -252,7 +252,16 @@ while read commit parents; do
|
||||
git read-tree -i -m $commit
|
||||
;;
|
||||
*)
|
||||
git read-tree -i -m $commit:"$filter_subdir"
|
||||
# The commit may not have the subdirectory at all
|
||||
err=$(git read-tree -i -m $commit:"$filter_subdir" 2>&1) || {
|
||||
if ! git rev-parse --verify $commit:"$filter_subdir" 2>/dev/null
|
||||
then
|
||||
rm -f "$GIT_INDEX_FILE"
|
||||
else
|
||||
echo >&2 "$err"
|
||||
false
|
||||
fi
|
||||
}
|
||||
esac || die "Could not initialize the index"
|
||||
|
||||
GIT_COMMIT=$commit
|
||||
|
||||
@@ -376,7 +376,7 @@ fi
|
||||
if test -z "$do_merge"
|
||||
then
|
||||
git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD |
|
||||
git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" &&
|
||||
git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
|
||||
move_to_original_branch
|
||||
ret=$?
|
||||
test 0 != $ret -a -d .dotest &&
|
||||
|
||||
@@ -153,20 +153,6 @@ cmd_add()
|
||||
usage
|
||||
fi
|
||||
|
||||
case "$repo" in
|
||||
./*|../*)
|
||||
# dereference source url relative to parent's url
|
||||
realrepo="$(resolve_relative_url $repo)" ;;
|
||||
*)
|
||||
# Turn the source into an absolute path if
|
||||
# it is local
|
||||
if base=$(get_repo_base "$repo"); then
|
||||
repo="$base"
|
||||
fi
|
||||
realrepo=$repo
|
||||
;;
|
||||
esac
|
||||
|
||||
# Guess path from repo if not specified or strip trailing slashes
|
||||
if test -z "$path"; then
|
||||
path=$(echo "$repo" | sed -e 's|/*$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
|
||||
@@ -174,15 +160,39 @@ cmd_add()
|
||||
path=$(echo "$path" | sed -e 's|/*$||')
|
||||
fi
|
||||
|
||||
test -e "$path" &&
|
||||
die "'$path' already exists"
|
||||
|
||||
git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
|
||||
die "'$path' already exists in the index"
|
||||
|
||||
module_clone "$path" "$realrepo" || exit
|
||||
(unset GIT_DIR; cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) ||
|
||||
die "Unable to checkout submodule '$path'"
|
||||
# perhaps the path exists and is already a git repo, else clone it
|
||||
if test -e "$path"
|
||||
then
|
||||
if test -d "$path/.git" &&
|
||||
test "$(unset GIT_DIR; cd $path; git rev-parse --git-dir)" = ".git"
|
||||
then
|
||||
echo "Adding existing repo at '$path' to the index"
|
||||
else
|
||||
die "'$path' already exists and is not a valid git repo"
|
||||
fi
|
||||
else
|
||||
case "$repo" in
|
||||
./*|../*)
|
||||
# dereference source url relative to parent's url
|
||||
realrepo="$(resolve_relative_url $repo)" ;;
|
||||
*)
|
||||
# Turn the source into an absolute path if
|
||||
# it is local
|
||||
if base=$(get_repo_base "$repo"); then
|
||||
repo="$base"
|
||||
fi
|
||||
realrepo=$repo
|
||||
;;
|
||||
esac
|
||||
|
||||
module_clone "$path" "$realrepo" || exit
|
||||
(unset GIT_DIR; cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) ||
|
||||
die "Unable to checkout submodule '$path'"
|
||||
fi
|
||||
|
||||
git add "$path" ||
|
||||
die "Failed to add submodule '$path'"
|
||||
|
||||
|
||||
@@ -1540,9 +1540,14 @@ sub find_by_url { # repos_root and, path are optional
|
||||
$remotes->{$repo_id}->{$_});
|
||||
}
|
||||
my $p = $path;
|
||||
my $rwr = rewrite_root({repo_id => $repo_id});
|
||||
unless (defined $p) {
|
||||
$p = $full_url;
|
||||
$p =~ s#^\Q$u\E(?:/|$)## or next;
|
||||
my $z = $u;
|
||||
if ($rwr) {
|
||||
$z = $rwr;
|
||||
}
|
||||
$p =~ s#^\Q$z\E(?:/|$)## or next;
|
||||
}
|
||||
foreach my $f (keys %$fetch) {
|
||||
next if $f ne $p;
|
||||
|
||||
@@ -5305,51 +5305,19 @@ sub git_search {
|
||||
print "<table class=\"pickaxe search\">\n";
|
||||
my $alternate = 1;
|
||||
$/ = "\n";
|
||||
my $git_command = git_cmd_str();
|
||||
my $searchqtext = $searchtext;
|
||||
$searchqtext =~ s/'/'\\''/;
|
||||
my $pickaxe_flags = $search_use_regexp ? '--pickaxe-regex' : '';
|
||||
open my $fd, "-|", "$git_command rev-list $hash | " .
|
||||
"$git_command diff-tree -r --stdin -S\'$searchqtext\' $pickaxe_flags";
|
||||
open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts,
|
||||
'--pretty=format:%H', '--no-abbrev', '--raw', "-S$searchtext",
|
||||
($search_use_regexp ? '--pickaxe-regex' : ());
|
||||
undef %co;
|
||||
my @files;
|
||||
while (my $line = <$fd>) {
|
||||
if (%co && $line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/) {
|
||||
my %set;
|
||||
$set{'file'} = $6;
|
||||
$set{'from_id'} = $3;
|
||||
$set{'to_id'} = $4;
|
||||
$set{'id'} = $set{'to_id'};
|
||||
if ($set{'id'} =~ m/0{40}/) {
|
||||
$set{'id'} = $set{'from_id'};
|
||||
}
|
||||
if ($set{'id'} =~ m/0{40}/) {
|
||||
next;
|
||||
}
|
||||
push @files, \%set;
|
||||
} elsif ($line =~ m/^([0-9a-fA-F]{40})$/){
|
||||
chomp $line;
|
||||
next unless $line;
|
||||
|
||||
my %set = parse_difftree_raw_line($line);
|
||||
if (defined $set{'commit'}) {
|
||||
# finish previous commit
|
||||
if (%co) {
|
||||
if ($alternate) {
|
||||
print "<tr class=\"dark\">\n";
|
||||
} else {
|
||||
print "<tr class=\"light\">\n";
|
||||
}
|
||||
$alternate ^= 1;
|
||||
my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
|
||||
print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
|
||||
"<td><i>" . $author . "</i></td>\n" .
|
||||
"<td>" .
|
||||
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
|
||||
-class => "list subject"},
|
||||
chop_and_escape_str($co{'title'}, 50) . "<br/>");
|
||||
while (my $setref = shift @files) {
|
||||
my %set = %$setref;
|
||||
print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
|
||||
hash=>$set{'id'}, file_name=>$set{'file'}),
|
||||
-class => "list"},
|
||||
"<span class=\"match\">" . esc_path($set{'file'}) . "</span>") .
|
||||
"<br/>\n";
|
||||
}
|
||||
print "</td>\n" .
|
||||
"<td class=\"link\">" .
|
||||
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
|
||||
@@ -5358,11 +5326,44 @@ sub git_search {
|
||||
print "</td>\n" .
|
||||
"</tr>\n";
|
||||
}
|
||||
%co = parse_commit($1);
|
||||
|
||||
if ($alternate) {
|
||||
print "<tr class=\"dark\">\n";
|
||||
} else {
|
||||
print "<tr class=\"light\">\n";
|
||||
}
|
||||
$alternate ^= 1;
|
||||
%co = parse_commit($set{'commit'});
|
||||
my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
|
||||
print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
|
||||
"<td><i>$author</i></td>\n" .
|
||||
"<td>" .
|
||||
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
|
||||
-class => "list subject"},
|
||||
chop_and_escape_str($co{'title'}, 50) . "<br/>");
|
||||
} elsif (defined $set{'to_id'}) {
|
||||
next if ($set{'to_id'} =~ m/^0{40}$/);
|
||||
|
||||
print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
|
||||
hash=>$set{'to_id'}, file_name=>$set{'to_file'}),
|
||||
-class => "list"},
|
||||
"<span class=\"match\">" . esc_path($set{'file'}) . "</span>") .
|
||||
"<br/>\n";
|
||||
}
|
||||
}
|
||||
close $fd;
|
||||
|
||||
# finish last commit (warning: repetition!)
|
||||
if (%co) {
|
||||
print "</td>\n" .
|
||||
"<td class=\"link\">" .
|
||||
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
|
||||
" | " .
|
||||
$cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
|
||||
print "</td>\n" .
|
||||
"</tr>\n";
|
||||
}
|
||||
|
||||
print "</table>\n";
|
||||
}
|
||||
|
||||
|
||||
2
ident.c
2
ident.c
@@ -171,7 +171,7 @@ static const char au_env[] = "GIT_AUTHOR_NAME";
|
||||
static const char co_env[] = "GIT_COMMITTER_NAME";
|
||||
static const char *env_hint =
|
||||
"\n"
|
||||
"*** Your name cannot be determined from your system services (gecos).\n"
|
||||
"*** Please tell me who you are.\n"
|
||||
"\n"
|
||||
"Run\n"
|
||||
"\n"
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
struct optparse_t {
|
||||
const char **argv;
|
||||
int argc;
|
||||
const char **out;
|
||||
int argc, cpidx;
|
||||
const char *opt;
|
||||
};
|
||||
|
||||
@@ -159,6 +160,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
|
||||
continue;
|
||||
|
||||
rest = skip_prefix(arg, options->long_name);
|
||||
if (options->type == OPTION_ARGUMENT) {
|
||||
if (!rest)
|
||||
continue;
|
||||
if (*rest == '=')
|
||||
return opterror(options, "takes no value", flags);
|
||||
if (*rest)
|
||||
continue;
|
||||
p->out[p->cpidx++] = arg - 2;
|
||||
return 0;
|
||||
}
|
||||
if (!rest) {
|
||||
/* abbreviated? */
|
||||
if (!strncmp(options->long_name, arg, arg_end - arg)) {
|
||||
@@ -242,14 +253,13 @@ static NORETURN void usage_with_options_internal(const char * const *,
|
||||
int parse_options(int argc, const char **argv, const struct option *options,
|
||||
const char * const usagestr[], int flags)
|
||||
{
|
||||
struct optparse_t args = { argv + 1, argc - 1, NULL };
|
||||
int j = 0;
|
||||
struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };
|
||||
|
||||
for (; args.argc; args.argc--, args.argv++) {
|
||||
const char *arg = args.argv[0];
|
||||
|
||||
if (*arg != '-' || !arg[1]) {
|
||||
argv[j++] = args.argv[0];
|
||||
args.out[args.cpidx++] = args.argv[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -286,9 +296,9 @@ int parse_options(int argc, const char **argv, const struct option *options,
|
||||
usage_with_options(usagestr, options);
|
||||
}
|
||||
|
||||
memmove(argv + j, args.argv, args.argc * sizeof(*argv));
|
||||
argv[j + args.argc] = NULL;
|
||||
return j + args.argc;
|
||||
memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));
|
||||
args.out[args.cpidx + args.argc] = NULL;
|
||||
return args.cpidx + args.argc;
|
||||
}
|
||||
|
||||
#define USAGE_OPTS_WIDTH 24
|
||||
@@ -328,6 +338,8 @@ void usage_with_options_internal(const char * const *usagestr,
|
||||
pos += fprintf(stderr, "--%s", opts->long_name);
|
||||
|
||||
switch (opts->type) {
|
||||
case OPTION_ARGUMENT:
|
||||
break;
|
||||
case OPTION_INTEGER:
|
||||
if (opts->flags & PARSE_OPT_OPTARG)
|
||||
pos += fprintf(stderr, " [<n>]");
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
enum parse_opt_type {
|
||||
/* special types */
|
||||
OPTION_END,
|
||||
OPTION_ARGUMENT,
|
||||
OPTION_GROUP,
|
||||
/* options with no arguments */
|
||||
OPTION_BIT,
|
||||
@@ -84,6 +85,7 @@ struct option {
|
||||
};
|
||||
|
||||
#define OPT_END() { OPTION_END }
|
||||
#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
|
||||
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
|
||||
#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
|
||||
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
|
||||
|
||||
42
quote.c
42
quote.c
@@ -260,6 +260,48 @@ extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
|
||||
fputc(terminator, fp);
|
||||
}
|
||||
|
||||
/* quote path as relative to the given prefix */
|
||||
char *quote_path_relative(const char *in, int len,
|
||||
struct strbuf *out, const char *prefix)
|
||||
{
|
||||
int needquote;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen(in);
|
||||
|
||||
/* "../" prefix itself does not need quoting, but "in" might. */
|
||||
needquote = next_quote_pos(in, len) < len;
|
||||
strbuf_setlen(out, 0);
|
||||
strbuf_grow(out, len);
|
||||
|
||||
if (needquote)
|
||||
strbuf_addch(out, '"');
|
||||
if (prefix) {
|
||||
int off = 0;
|
||||
while (prefix[off] && off < len && prefix[off] == in[off])
|
||||
if (prefix[off] == '/') {
|
||||
prefix += off + 1;
|
||||
in += off + 1;
|
||||
len -= off + 1;
|
||||
off = 0;
|
||||
} else
|
||||
off++;
|
||||
|
||||
for (; *prefix; prefix++)
|
||||
if (*prefix == '/')
|
||||
strbuf_addstr(out, "../");
|
||||
}
|
||||
|
||||
quote_c_style_counted (in, len, out, NULL, 1);
|
||||
|
||||
if (needquote)
|
||||
strbuf_addch(out, '"');
|
||||
if (!out->len)
|
||||
strbuf_addstr(out, "./");
|
||||
|
||||
return out->buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* C-style name unquoting.
|
||||
*
|
||||
|
||||
4
quote.h
4
quote.h
@@ -47,6 +47,10 @@ extern void write_name_quoted(const char *name, FILE *, int terminator);
|
||||
extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
|
||||
const char *name, FILE *, int terminator);
|
||||
|
||||
/* quote path as relative to the given prefix */
|
||||
char *quote_path_relative(const char *in, int len,
|
||||
struct strbuf *out, const char *prefix);
|
||||
|
||||
/* quoting as a string literal for other languages */
|
||||
extern void perl_quote_print(FILE *stream, const char *src);
|
||||
extern void python_quote_print(FILE *stream, const char *src);
|
||||
|
||||
2
setup.c
2
setup.c
@@ -234,6 +234,8 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
|
||||
const char *p = prefix_path(prefix, prefixlen, *src);
|
||||
if (p)
|
||||
*(dst++) = p;
|
||||
else
|
||||
exit(128); /* error message already given */
|
||||
src++;
|
||||
}
|
||||
*dst = NULL;
|
||||
|
||||
@@ -21,6 +21,9 @@ string options
|
||||
--st <st> get another string (pervert ordering)
|
||||
-o <str> get another string
|
||||
|
||||
magic arguments
|
||||
--quux means --quux
|
||||
|
||||
EOF
|
||||
|
||||
test_expect_success 'test help' '
|
||||
@@ -114,4 +117,17 @@ test_expect_success 'detect possible typos' '
|
||||
git diff expect.err output.err
|
||||
'
|
||||
|
||||
cat > expect <<EOF
|
||||
boolean: 0
|
||||
integer: 0
|
||||
string: (not set)
|
||||
arg 00: --quux
|
||||
EOF
|
||||
|
||||
test_expect_success 'keep some options as arguments' '
|
||||
test-parse-options --quux > output 2> output.err &&
|
||||
test ! -s output.err &&
|
||||
git diff expect output
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
30
t/t1005-read-tree-reset.sh
Executable file
30
t/t1005-read-tree-reset.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='read-tree -u --reset'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
# two-tree test
|
||||
|
||||
test_expect_success 'setup' '
|
||||
git init &&
|
||||
mkdir df &&
|
||||
echo content >df/file &&
|
||||
git add df/file &&
|
||||
git commit -m one &&
|
||||
git ls-files >expect &&
|
||||
rm -rf df &&
|
||||
echo content >df &&
|
||||
git add df &&
|
||||
echo content >new &&
|
||||
git add new &&
|
||||
git commit -m two
|
||||
'
|
||||
|
||||
test_expect_failure 'reset should work' '
|
||||
git read-tree -u --reset HEAD^ &&
|
||||
git ls-files >actual &&
|
||||
diff -u expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
@@ -120,7 +120,7 @@ EOF
|
||||
# having 1.txt and path3
|
||||
test_expect_success \
|
||||
'ls-tree filter odd names' \
|
||||
'git ls-tree $tree 1.txt /1.txt //1.txt path3/1.txt /path3/1.txt //path3//1.txt path3 /path3/ path3// >current &&
|
||||
'git ls-tree $tree 1.txt ./1.txt .//1.txt path3/1.txt path3/./1.txt path3 path3// >current &&
|
||||
cat >expected <<\EOF &&
|
||||
100644 blob X 1.txt
|
||||
100644 blob X path3/1.txt
|
||||
|
||||
72
t/t4150-am-subdir.sh
Executable file
72
t/t4150-am-subdir.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='git am running from a subdirectory'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success setup '
|
||||
echo hello >world &&
|
||||
git add world &&
|
||||
test_tick &&
|
||||
git commit -m initial &&
|
||||
git tag initial &&
|
||||
echo goodbye >world &&
|
||||
git add world &&
|
||||
test_tick &&
|
||||
git commit -m second &&
|
||||
git format-patch --stdout HEAD^ >patchfile &&
|
||||
: >expect
|
||||
'
|
||||
|
||||
test_expect_success 'am regularly from stdin' '
|
||||
git checkout initial &&
|
||||
git am <patchfile &&
|
||||
git diff master >actual &&
|
||||
diff -u expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'am regularly from file' '
|
||||
git checkout initial &&
|
||||
git am patchfile &&
|
||||
git diff master >actual &&
|
||||
diff -u expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'am regularly from stdin in subdirectory' '
|
||||
rm -fr subdir &&
|
||||
git checkout initial &&
|
||||
(
|
||||
mkdir -p subdir &&
|
||||
cd subdir &&
|
||||
git am <../patchfile
|
||||
) &&
|
||||
git diff master>actual &&
|
||||
diff -u expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'am regularly from file in subdirectory' '
|
||||
rm -fr subdir &&
|
||||
git checkout initial &&
|
||||
(
|
||||
mkdir -p subdir &&
|
||||
cd subdir &&
|
||||
git am ../patchfile
|
||||
) &&
|
||||
git diff master >actual &&
|
||||
diff -u expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'am regularly from file in subdirectory with full path' '
|
||||
rm -fr subdir &&
|
||||
git checkout initial &&
|
||||
P=$(pwd) &&
|
||||
(
|
||||
mkdir -p subdir &&
|
||||
cd subdir &&
|
||||
git am "$P/patchfile"
|
||||
) &&
|
||||
git diff master >actual &&
|
||||
diff -u expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
84
t/t5305-include-tag.sh
Executable file
84
t/t5305-include-tag.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='git-pack-object --include-tag'
|
||||
. ./test-lib.sh
|
||||
|
||||
TRASH=`pwd`
|
||||
|
||||
test_expect_success setup '
|
||||
echo c >d &&
|
||||
git update-index --add d &&
|
||||
tree=`git write-tree` &&
|
||||
commit=`git commit-tree $tree </dev/null` &&
|
||||
echo "object $commit" >sig &&
|
||||
echo "type commit" >>sig &&
|
||||
echo "tag mytag" >>sig &&
|
||||
echo "tagger $(git var GIT_COMMITTER_IDENT)" >>sig &&
|
||||
echo >>sig &&
|
||||
echo "our test tag" >>sig &&
|
||||
tag=`git mktag <sig` &&
|
||||
rm d sig &&
|
||||
git update-ref refs/tags/mytag $tag && {
|
||||
echo $tree &&
|
||||
echo $commit &&
|
||||
git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/"
|
||||
} >obj-list
|
||||
'
|
||||
|
||||
rm -rf clone.git
|
||||
test_expect_success 'pack without --include-tag' '
|
||||
packname_1=$(git pack-objects \
|
||||
--window=0 \
|
||||
test-1 <obj-list)
|
||||
'
|
||||
|
||||
test_expect_success 'unpack objects' '
|
||||
(
|
||||
GIT_DIR=clone.git &&
|
||||
export GIT_DIR &&
|
||||
git init &&
|
||||
git unpack-objects -n <test-1-${packname_1}.pack &&
|
||||
git unpack-objects <test-1-${packname_1}.pack
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'check unpacked result (have commit, no tag)' '
|
||||
git rev-list --objects $commit >list.expect &&
|
||||
(
|
||||
GIT_DIR=clone.git &&
|
||||
export GIT_DIR &&
|
||||
test_must_fail git cat-file -e $tag &&
|
||||
git rev-list --objects $commit
|
||||
) >list.actual &&
|
||||
git diff list.expect list.actual
|
||||
'
|
||||
|
||||
rm -rf clone.git
|
||||
test_expect_success 'pack with --include-tag' '
|
||||
packname_1=$(git pack-objects \
|
||||
--window=0 \
|
||||
--include-tag \
|
||||
test-2 <obj-list)
|
||||
'
|
||||
|
||||
test_expect_success 'unpack objects' '
|
||||
(
|
||||
GIT_DIR=clone.git &&
|
||||
export GIT_DIR &&
|
||||
git init &&
|
||||
git unpack-objects -n <test-2-${packname_1}.pack &&
|
||||
git unpack-objects <test-2-${packname_1}.pack
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'check unpacked result (have commit, have tag)' '
|
||||
git rev-list --objects mytag >list.expect &&
|
||||
(
|
||||
GIT_DIR=clone.git &&
|
||||
export GIT_DIR &&
|
||||
git rev-list --objects $tag
|
||||
) >list.actual &&
|
||||
git diff list.expect list.actual
|
||||
'
|
||||
|
||||
test_done
|
||||
150
t/t5503-tagfollow.sh
Executable file
150
t/t5503-tagfollow.sh
Executable file
@@ -0,0 +1,150 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='test automatic tag following'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
# End state of the repository:
|
||||
#
|
||||
# T - tag1 S - tag2
|
||||
# / /
|
||||
# L - A ------ O ------ B
|
||||
# \ \ \
|
||||
# \ C - origin/cat \
|
||||
# origin/master master
|
||||
|
||||
test_expect_success setup '
|
||||
test_tick &&
|
||||
echo ichi >file &&
|
||||
git add file &&
|
||||
git commit -m L &&
|
||||
L=$(git rev-parse --verify HEAD) &&
|
||||
|
||||
(
|
||||
mkdir cloned &&
|
||||
cd cloned &&
|
||||
git init-db &&
|
||||
git remote add -f origin ..
|
||||
) &&
|
||||
|
||||
test_tick &&
|
||||
echo A >file &&
|
||||
git add file &&
|
||||
git commit -m A &&
|
||||
A=$(git rev-parse --verify HEAD)
|
||||
'
|
||||
|
||||
U=UPLOAD_LOG
|
||||
|
||||
cat - <<EOF >expect
|
||||
#S
|
||||
want $A
|
||||
#E
|
||||
EOF
|
||||
test_expect_success 'fetch A (new commit : 1 connection)' '
|
||||
rm -f $U
|
||||
(
|
||||
cd cloned &&
|
||||
GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U &&
|
||||
test $A = $(git rev-parse --verify origin/master)
|
||||
) &&
|
||||
test -s $U &&
|
||||
cut -d" " -f1,2 $U >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success "create tag T on A, create C on branch cat" '
|
||||
git tag -a -m tag1 tag1 $A &&
|
||||
T=$(git rev-parse --verify tag1) &&
|
||||
|
||||
git checkout -b cat &&
|
||||
echo C >file &&
|
||||
git add file &&
|
||||
git commit -m C &&
|
||||
C=$(git rev-parse --verify HEAD) &&
|
||||
git checkout master
|
||||
'
|
||||
|
||||
cat - <<EOF >expect
|
||||
#S
|
||||
want $C
|
||||
want $T
|
||||
#E
|
||||
EOF
|
||||
test_expect_success 'fetch C, T (new branch, tag : 1 connection)' '
|
||||
rm -f $U
|
||||
(
|
||||
cd cloned &&
|
||||
GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U &&
|
||||
test $C = $(git rev-parse --verify origin/cat) &&
|
||||
test $T = $(git rev-parse --verify tag1) &&
|
||||
test $A = $(git rev-parse --verify tag1^0)
|
||||
) &&
|
||||
test -s $U &&
|
||||
cut -d" " -f1,2 $U >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_expect_success "create commits O, B, tag S on B" '
|
||||
test_tick &&
|
||||
echo O >file &&
|
||||
git add file &&
|
||||
git commit -m O &&
|
||||
|
||||
test_tick &&
|
||||
echo B >file &&
|
||||
git add file &&
|
||||
git commit -m B &&
|
||||
B=$(git rev-parse --verify HEAD) &&
|
||||
|
||||
git tag -a -m tag2 tag2 $B &&
|
||||
S=$(git rev-parse --verify tag2)
|
||||
'
|
||||
|
||||
cat - <<EOF >expect
|
||||
#S
|
||||
want $B
|
||||
want $S
|
||||
#E
|
||||
EOF
|
||||
test_expect_success 'fetch B, S (commit and tag : 1 connection)' '
|
||||
rm -f $U
|
||||
(
|
||||
cd cloned &&
|
||||
GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U &&
|
||||
test $B = $(git rev-parse --verify origin/master) &&
|
||||
test $B = $(git rev-parse --verify tag2^0) &&
|
||||
test $S = $(git rev-parse --verify tag2)
|
||||
) &&
|
||||
test -s $U &&
|
||||
cut -d" " -f1,2 $U >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
cat - <<EOF >expect
|
||||
#S
|
||||
want $B
|
||||
want $S
|
||||
#E
|
||||
EOF
|
||||
test_expect_success 'new clone fetch master and tags' '
|
||||
git branch -D cat
|
||||
rm -f $U
|
||||
(
|
||||
mkdir clone2 &&
|
||||
cd clone2 &&
|
||||
git init &&
|
||||
git remote add origin .. &&
|
||||
GIT_DEBUG_SEND_PACK=3 git fetch 3>../$U &&
|
||||
test $B = $(git rev-parse --verify origin/master) &&
|
||||
test $S = $(git rev-parse --verify tag2) &&
|
||||
test $B = $(git rev-parse --verify tag2^0) &&
|
||||
test $T = $(git rev-parse --verify tag1) &&
|
||||
test $A = $(git rev-parse --verify tag1^0)
|
||||
) &&
|
||||
test -s $U &&
|
||||
cut -d" " -f1,2 $U >actual &&
|
||||
git diff expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
@@ -179,4 +179,28 @@ test_expect_success 'Name needing quotes' '
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'Subdirectory filter with disappearing trees' '
|
||||
git reset --hard &&
|
||||
git checkout master &&
|
||||
|
||||
mkdir foo &&
|
||||
touch foo/bar &&
|
||||
git add foo &&
|
||||
test_tick &&
|
||||
git commit -m "Adding foo" &&
|
||||
|
||||
git rm -r foo &&
|
||||
test_tick &&
|
||||
git commit -m "Removing foo" &&
|
||||
|
||||
mkdir foo &&
|
||||
touch foo/bar &&
|
||||
git add foo &&
|
||||
test_tick &&
|
||||
git commit -m "Re-adding foo" &&
|
||||
|
||||
git filter-branch -f --subdirectory-filter foo &&
|
||||
test $(git rev-list master | wc -l) = 3
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -142,15 +142,16 @@ test_expect_success 'setup deeper work tree' '
|
||||
test_expect_success 'add a directory outside the work tree' '(
|
||||
cd tester &&
|
||||
d1="$(cd .. ; pwd)" &&
|
||||
git add "$d1"
|
||||
test_must_fail git add "$d1"
|
||||
)'
|
||||
|
||||
|
||||
test_expect_success 'add a file outside the work tree, nasty case 1' '(
|
||||
cd tester &&
|
||||
f="$(pwd)x" &&
|
||||
echo "$f" &&
|
||||
touch "$f" &&
|
||||
git add "$f"
|
||||
test_must_fail git add "$f"
|
||||
)'
|
||||
|
||||
test_expect_success 'add a file outside the work tree, nasty case 2' '(
|
||||
@@ -158,7 +159,7 @@ test_expect_success 'add a file outside the work tree, nasty case 2' '(
|
||||
f="$(pwd | sed "s/.$//")x" &&
|
||||
echo "$f" &&
|
||||
touch "$f" &&
|
||||
git add "$f"
|
||||
test_must_fail git add "$f"
|
||||
)'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -89,6 +89,58 @@ test_expect_success 'git-clean with prefix' '
|
||||
test -f build/lib.so
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'git-clean with relative prefix' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
|
||||
would_clean=$(
|
||||
cd docs &&
|
||||
git clean -n ../src |
|
||||
sed -n -e "s|^Would remove ||p"
|
||||
) &&
|
||||
test "$would_clean" = ../src/part3.c || {
|
||||
echo "OOps <$would_clean>"
|
||||
false
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'git-clean with absolute path' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
|
||||
would_clean=$(
|
||||
cd docs &&
|
||||
git clean -n $(pwd)/../src |
|
||||
sed -n -e "s|^Would remove ||p"
|
||||
) &&
|
||||
test "$would_clean" = ../src/part3.c || {
|
||||
echo "OOps <$would_clean>"
|
||||
false
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'git-clean with out of work tree relative path' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
|
||||
(
|
||||
cd docs &&
|
||||
test_must_fail git clean -n ../..
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'git-clean with out of work tree absolute path' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
|
||||
dd=$(cd .. && pwd) &&
|
||||
(
|
||||
cd docs &&
|
||||
test_must_fail git clean -n $dd
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'git-clean -d with prefix and path' '
|
||||
|
||||
mkdir -p build docs src/feature &&
|
||||
|
||||
@@ -869,6 +869,8 @@ zcommits
|
||||
COMMIT
|
||||
reset refs/tags/O3-2nd
|
||||
from :5
|
||||
reset refs/tags/O3-3rd
|
||||
from :5
|
||||
INPUT_END
|
||||
|
||||
cat >expect <<INPUT_END
|
||||
|
||||
@@ -20,6 +20,8 @@ int main(int argc, const char **argv)
|
||||
OPT_STRING(0, "string2", &string, "str", "get another string"),
|
||||
OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
|
||||
OPT_STRING('o', NULL, &string, "str", "get another string"),
|
||||
OPT_GROUP("magic arguments"),
|
||||
OPT_ARGUMENT("quux", "means --quux"),
|
||||
OPT_END(),
|
||||
};
|
||||
int i;
|
||||
|
||||
@@ -560,6 +560,7 @@ static int close_bundle(struct transport *transport)
|
||||
struct git_transport_data {
|
||||
unsigned thin : 1;
|
||||
unsigned keep : 1;
|
||||
unsigned followtags : 1;
|
||||
int depth;
|
||||
struct child_process *conn;
|
||||
int fd[2];
|
||||
@@ -580,6 +581,9 @@ static int set_git_option(struct transport *connection,
|
||||
} else if (!strcmp(name, TRANS_OPT_THIN)) {
|
||||
data->thin = !!value;
|
||||
return 0;
|
||||
} else if (!strcmp(name, TRANS_OPT_FOLLOWTAGS)) {
|
||||
data->followtags = !!value;
|
||||
return 0;
|
||||
} else if (!strcmp(name, TRANS_OPT_KEEP)) {
|
||||
data->keep = !!value;
|
||||
return 0;
|
||||
@@ -628,6 +632,7 @@ static int fetch_refs_via_pack(struct transport *transport,
|
||||
args.keep_pack = data->keep;
|
||||
args.lock_pack = 1;
|
||||
args.use_thin_pack = data->thin;
|
||||
args.include_tag = data->followtags;
|
||||
args.verbose = transport->verbose > 0;
|
||||
args.depth = data->depth;
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ struct transport *transport_get(struct remote *, const char *);
|
||||
/* Limit the depth of the fetch if not null */
|
||||
#define TRANS_OPT_DEPTH "depth"
|
||||
|
||||
/* Aggressively fetch annotated tags if possible */
|
||||
#define TRANS_OPT_FOLLOWTAGS "followtags"
|
||||
|
||||
/**
|
||||
* Returns 0 if the option was used, non-zero otherwise. Prints a
|
||||
* message to stderr if the option is not used.
|
||||
|
||||
@@ -27,7 +27,8 @@ static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=n
|
||||
static unsigned long oldest_have;
|
||||
|
||||
static int multi_ack, nr_our_refs;
|
||||
static int use_thin_pack, use_ofs_delta, no_progress;
|
||||
static int use_thin_pack, use_ofs_delta, use_include_tag;
|
||||
static int no_progress;
|
||||
static struct object_array have_obj;
|
||||
static struct object_array want_obj;
|
||||
static unsigned int timeout;
|
||||
@@ -35,6 +36,7 @@ static unsigned int timeout;
|
||||
* otherwise maximum packet size (up to 65520 bytes).
|
||||
*/
|
||||
static int use_sideband;
|
||||
static int debug_fd;
|
||||
|
||||
static void reset_timeout(void)
|
||||
{
|
||||
@@ -163,6 +165,8 @@ static void create_pack_file(void)
|
||||
argv[arg++] = "--progress";
|
||||
if (use_ofs_delta)
|
||||
argv[arg++] = "--delta-base-offset";
|
||||
if (use_include_tag)
|
||||
argv[arg++] = "--include-tag";
|
||||
argv[arg++] = NULL;
|
||||
|
||||
memset(&pack_objects, 0, sizeof(pack_objects));
|
||||
@@ -446,6 +450,8 @@ static void receive_needs(void)
|
||||
static char line[1000];
|
||||
int len, depth = 0;
|
||||
|
||||
if (debug_fd)
|
||||
write_in_full(debug_fd, "#S\n", 3);
|
||||
for (;;) {
|
||||
struct object *o;
|
||||
unsigned char sha1_buf[20];
|
||||
@@ -453,6 +459,8 @@ static void receive_needs(void)
|
||||
reset_timeout();
|
||||
if (!len)
|
||||
break;
|
||||
if (debug_fd)
|
||||
write_in_full(debug_fd, line, len);
|
||||
|
||||
if (!prefixcmp(line, "shallow ")) {
|
||||
unsigned char sha1[20];
|
||||
@@ -491,6 +499,8 @@ static void receive_needs(void)
|
||||
use_sideband = DEFAULT_PACKET_MAX;
|
||||
if (strstr(line+45, "no-progress"))
|
||||
no_progress = 1;
|
||||
if (strstr(line+45, "include-tag"))
|
||||
use_include_tag = 1;
|
||||
|
||||
/* We have sent all our refs already, and the other end
|
||||
* should have chosen out of them; otherwise they are
|
||||
@@ -508,6 +518,8 @@ static void receive_needs(void)
|
||||
add_object_array(o, NULL, &want_obj);
|
||||
}
|
||||
}
|
||||
if (debug_fd)
|
||||
write_in_full(debug_fd, "#E\n", 3);
|
||||
if (depth == 0 && shallows.nr == 0)
|
||||
return;
|
||||
if (depth > 0) {
|
||||
@@ -560,7 +572,8 @@ static void receive_needs(void)
|
||||
static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
|
||||
{
|
||||
static const char *capabilities = "multi_ack thin-pack side-band"
|
||||
" side-band-64k ofs-delta shallow no-progress";
|
||||
" side-band-64k ofs-delta shallow no-progress"
|
||||
" include-tag";
|
||||
struct object *o = parse_object(sha1);
|
||||
|
||||
if (!o)
|
||||
@@ -633,6 +646,8 @@ int main(int argc, char **argv)
|
||||
die("'%s': unable to chdir or not a git archive", dir);
|
||||
if (is_repository_shallow())
|
||||
die("attempt to fetch/clone from a shallow repository");
|
||||
if (getenv("GIT_DEBUG_SEND_PACK"))
|
||||
debug_fd = atoi(getenv("GIT_DEBUG_SEND_PACK"));
|
||||
upload_pack();
|
||||
return 0;
|
||||
}
|
||||
|
||||
47
wt-status.c
47
wt-status.c
@@ -7,6 +7,7 @@
|
||||
#include "diff.h"
|
||||
#include "revision.h"
|
||||
#include "diffcore.h"
|
||||
#include "quote.h"
|
||||
|
||||
int wt_status_relative_paths = 1;
|
||||
int wt_status_use_color = -1;
|
||||
@@ -82,51 +83,7 @@ static void wt_status_print_trailer(struct wt_status *s)
|
||||
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
|
||||
}
|
||||
|
||||
static char *quote_path(const char *in, int len,
|
||||
struct strbuf *out, const char *prefix)
|
||||
{
|
||||
if (len < 0)
|
||||
len = strlen(in);
|
||||
|
||||
strbuf_grow(out, len);
|
||||
strbuf_setlen(out, 0);
|
||||
if (prefix) {
|
||||
int off = 0;
|
||||
while (prefix[off] && off < len && prefix[off] == in[off])
|
||||
if (prefix[off] == '/') {
|
||||
prefix += off + 1;
|
||||
in += off + 1;
|
||||
len -= off + 1;
|
||||
off = 0;
|
||||
} else
|
||||
off++;
|
||||
|
||||
for (; *prefix; prefix++)
|
||||
if (*prefix == '/')
|
||||
strbuf_addstr(out, "../");
|
||||
}
|
||||
|
||||
for ( ; len > 0; in++, len--) {
|
||||
int ch = *in;
|
||||
|
||||
switch (ch) {
|
||||
case '\n':
|
||||
strbuf_addstr(out, "\\n");
|
||||
break;
|
||||
case '\r':
|
||||
strbuf_addstr(out, "\\r");
|
||||
break;
|
||||
default:
|
||||
strbuf_addch(out, ch);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!out->len)
|
||||
strbuf_addstr(out, "./");
|
||||
|
||||
return out->buf;
|
||||
}
|
||||
#define quote_path quote_path_relative
|
||||
|
||||
static void wt_status_print_filepair(struct wt_status *s,
|
||||
int t, struct diff_filepair *p)
|
||||
|
||||
Reference in New Issue
Block a user