Merge branch 'master' of git://repo.or.cz/alt-git

This commit is contained in:
Johannes Sixt
2007-11-06 08:24:22 +01:00
77 changed files with 1831 additions and 943 deletions

1
.gitignore vendored
View File

@@ -153,6 +153,7 @@ test-delta
test-dump-cache-tree
test-genrandom
test-match-trees
test-parse-options
test-sha1
common-cmds.h
*.tar.gz

View File

@@ -63,8 +63,8 @@ Fixes since v1.5.3.4
* Git segfaulted when reading an invalid .gitattributes file. Fixed.
* post-receive-email example hook fixed was fixed for
non-fast-forward updates.
* post-receive-email example hook was fixed for non-fast-forward
updates.
* Documentation updates for supported (but previously undocumented)
options of "git-archive" and "git-reflog".

View File

@@ -661,6 +661,15 @@ pack.threads::
machines. The required amount of memory for the delta search window
is however multiplied by the number of threads.
pack.indexVersion::
Specify the default pack index version. Valid values are 1 for
legacy pack index used by Git versions prior to 1.5.2, and 2 for
the new pack index with capabilities for packs larger than 4 GB
as well as proper protection against the repacking of corrupted
packs. Version 2 is selected and this config option ignored
whenever the corresponding pack is larger than 2 GB. Otherwise
the default is 1.
pull.octopus::
The default merge strategy to use when pulling multiple branches
at once.

View File

@@ -828,7 +828,7 @@ that branch, and do some work there.
------------------------------------------------
$ git checkout mybranch
$ echo "Work, work, work" >>hello
$ git commit -m 'Some work.' -i hello
$ git commit -m "Some work." -i hello
------------------------------------------------
Here, we just added another line to `hello`, and we used a shorthand for
@@ -853,7 +853,7 @@ hasn't happened in the `master` branch at all. Then do
------------
$ echo "Play, play, play" >>hello
$ echo "Lots of fun" >>example
$ git commit -m 'Some fun.' -i hello example
$ git commit -m "Some fun." -i hello example
------------
since the master branch is obviously in a much better mood.
@@ -1607,8 +1607,8 @@ in both of them. You could merge in 'diff-fix' first and then
'commit-fix' next, like this:
------------
$ git merge -m 'Merge fix in diff-fix' diff-fix
$ git merge -m 'Merge fix in commit-fix' commit-fix
$ git merge -m "Merge fix in diff-fix" diff-fix
$ git merge -m "Merge fix in commit-fix" commit-fix
------------
Which would result in:

View File

@@ -1,5 +1,5 @@
The output format from "git-diff-index", "git-diff-tree" and
"git-diff-files" are very similar.
The output format from "git-diff-index", "git-diff-tree",
"git-diff-files" and "git diff --raw" are very similar.
These commands all compare two sets of things; what is
compared differs:
@@ -62,7 +62,8 @@ respectively.
diff format for merges
----------------------
"git-diff-tree" and "git-diff-files" can take '-c' or '--cc' option
"git-diff-tree", "git-diff-files" and "git-diff --raw"
can take '-c' or '--cc' option
to generate diff output also for merge commits. The output differs
from the format described above in the following way:
@@ -86,10 +87,10 @@ Generating patches with -p
--------------------------
When "git-diff-index", "git-diff-tree", or "git-diff-files" are run
with a '-p' option, they do not produce the output described above;
instead they produce a patch file. You can customize the creation
of such patches via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS
environment variables.
with a '-p' option, or "git diff" without the '--raw' option, they
do not produce the output described above; instead they produce a
patch file. You can customize the creation of such patches via the
GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables.
What the -p option produces is slightly different from the traditional
diff format.
@@ -137,8 +138,8 @@ file made it into the new one.
combined diff format
--------------------
git-diff-tree and git-diff-files can take '-c' or '--cc' option
to produce 'combined diff', which looks like this:
"git-diff-tree", "git-diff-files" and "git-diff" can take '-c' or
'--cc' option to produce 'combined diff', which looks like this:
------------
diff --combined describe.c

View File

@@ -109,7 +109,7 @@ $ tar zxf frotz.tar.gz
$ cd frotz
$ git-init
$ git add . <1>
$ git commit -m 'import of frotz source tree.'
$ git commit -m "import of frotz source tree."
$ git tag v2.43 <2>
------------
+
@@ -300,7 +300,7 @@ $ git merge topic/one topic/two && git merge hold/linus <8>
$ git checkout maint
$ git cherry-pick master~4 <9>
$ compile/test
$ git tag -s -m 'GIT 0.99.9x' v0.99.9x <10>
$ git tag -s -m "GIT 0.99.9x" v0.99.9x <10>
$ git fetch ko && git show-branch master maint 'tags/ko-*' <11>
$ git push ko <12>
$ git push ko v0.99.9x <13>

View File

@@ -50,10 +50,10 @@ OPTIONS
and `dir/file2`) can be given to add all files in the
directory, recursively.
-n::
-n, \--dry-run::
Don't actually add the file(s), just show if they exist.
-v::
-v, \--verbose::
Be verbose.
-f::

View File

@@ -85,7 +85,7 @@ OPTIONS
-a::
List both remote-tracking branches and local branches.
-v::
-v, --verbose::
Show sha1 and commit subject line for each head.
--abbrev=<length>::

View File

@@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit
SYNOPSIS
--------
'git-cherry-pick' [--edit] [-n] [-x] <commit>
'git-cherry-pick' [--edit] [-n] [-m parent-number] [-x] <commit>
DESCRIPTION
-----------
@@ -44,6 +44,13 @@ OPTIONS
described above, and `-r` was to disable it. Now the
default is not to do `-x` so this option is a no-op.
-m parent-number|--mainline parent-number::
Usually you cannot revert a merge because you do not know which
side of the merge should be considered the mainline. This
option specifies the parent number (starting from 1) of
the mainline and allows cherry-pick to replay the change
relative to the specified parent.
-n|--no-commit::
Usually the command automatically creates a commit with
a commit log message stating which commit was

View File

@@ -12,7 +12,7 @@ SYNOPSIS
'git-clone' [--template=<template_directory>]
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare]
[-o <name>] [-u <upload-pack>] [--reference <repository>]
[--depth <depth>] <repository> [<directory>]
[--depth <depth>] [--] <repository> [<directory>]
DESCRIPTION
-----------

View File

@@ -82,6 +82,9 @@ include::diff-options.txt[]
the diff to the named paths (you can give directory
names and get diff for all files under them).
Output format
-------------
include::diff-format.txt[]
EXAMPLES
--------

View File

@@ -152,7 +152,7 @@ definition impossible to preserve signatures at any rate.)
does this in the '.git-rewrite/' directory but you can override
that choice by this parameter.
-f\|--force::
-f|--force::
`git filter-branch` refuses to start with an existing temporary
directory or when there are already refs starting with
'refs/original/', unless forced.

View File

@@ -34,7 +34,7 @@ OPTIONS
condition. An error happens when a source is neither existing nor
controlled by GIT, or when it would overwrite an existing
file unless '-f' is given.
-n::
-n, \--dry-run::
Do nothing; only show what would happen

View File

@@ -157,7 +157,7 @@ need to get to the other branch for a quick bugfix.
------------
$ git checkout feature ;# you were working in "feature" branch and
$ work work work ;# got interrupted
$ git commit -a -m 'snapshot WIP' <1>
$ git commit -a -m "snapshot WIP" <1>
$ git checkout master
$ fix fix fix
$ git commit ;# commit with real log

View File

@@ -7,7 +7,7 @@ git-revert - Revert an existing commit
SYNOPSIS
--------
'git-revert' [--edit | --no-edit] [-n] <commit>
'git-revert' [--edit | --no-edit] [-n] [-m parent-number] <commit>
DESCRIPTION
-----------
@@ -27,6 +27,13 @@ OPTIONS
message prior committing the revert. This is the default if
you run the command from a terminal.
-m parent-number|--mainline parent-number::
Usually you cannot revert a merge because you do not know which
side of the merge should be considered the mainline. This
option specifies the parent number (starting from 1) of
the mainline and allows revert to reverse the change
relative to the specified parent.
--no-edit::
With this option, `git-revert` will not start the commit
message editor.

View File

@@ -30,7 +30,7 @@ OPTIONS
-f::
Override the up-to-date check.
-n::
-n, \--dry-run::
Don't actually remove the file(s), just show if they exist in
the index.
@@ -51,7 +51,7 @@ OPTIONS
\--ignore-unmatch::
Exit with a zero status even if no files matched.
\--quiet::
-q, \--quiet::
git-rm normally outputs one line (in the form of an "rm" command)
for each file removed. This option suppresses that output.

View File

@@ -16,7 +16,7 @@ Remove multiple empty lines, and empty lines at beginning and end.
OPTIONS
-------
-s\|--strip-comments::
-s|--strip-comments::
In addition to empty lines, also strip lines starting with '#'.
<stream>::

View File

@@ -26,7 +26,7 @@ a regular file whose contents is `ref: refs/heads/master`.
OPTIONS
-------
-q::
-q, --quiet::
Do not issue an error message if the <name> is not a
symbolic ref but a detached HEAD; instead exit with
non-zero status silently.

View File

@@ -289,7 +289,7 @@ LIB_H = \
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
spawn-pipe.h \
utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
mailmap.h remote.h transport.h diffcore.h hash.h
mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h
DIFF_OBJS = \
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -313,7 +313,7 @@ LIB_OBJS = \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
transport.o bundle.o walker.o
transport.o bundle.o walker.o parse-options.o
BUILTIN_OBJS = \
builtin-add.o \
@@ -1006,7 +1006,7 @@ endif
### Testing rules
TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X
TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X
all:: $(TEST_PROGRAMS)

View File

@@ -13,9 +13,12 @@
#include "commit.h"
#include "revision.h"
#include "run-command.h"
#include "parse-options.h"
static const char builtin_add_usage[] =
"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] <filepattern>...";
static const char * const builtin_add_usage[] = {
"git-add [options] [--] <filepattern>...",
NULL
};
static int take_worktree_changes;
static const char *excludes_file;
@@ -162,21 +165,30 @@ static struct lock_file lock_file;
static const char ignore_error[] =
"The following paths are ignored by one of your .gitignore files:\n";
static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
static int add_interactive = 0;
static struct option builtin_add_options[] = {
OPT__DRY_RUN(&show_only),
OPT__VERBOSE(&verbose),
OPT_GROUP(""),
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"),
OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"),
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
OPT_END(),
};
int cmd_add(int argc, const char **argv, const char *prefix)
{
int i, newfd;
int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
int i, newfd, orig_argc = argc;
const char **pathspec;
struct dir_struct dir;
int add_interactive = 0;
for (i = 1; i < argc; i++) {
if (!strcmp("--interactive", argv[i]) ||
!strcmp("-i", argv[i]))
add_interactive++;
}
argc = parse_options(argc, argv, builtin_add_options,
builtin_add_usage, 0);
if (add_interactive) {
if (argc != 2)
if (add_interactive != 1 || orig_argc != 2)
die("add --interactive does not take any parameters");
exit(interactive_add());
}
@@ -185,51 +197,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
newfd = hold_locked_index(&lock_file, 1);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (arg[0] != '-')
break;
if (!strcmp(arg, "--")) {
i++;
break;
}
if (!strcmp(arg, "-n")) {
show_only = 1;
continue;
}
if (!strcmp(arg, "-f")) {
ignored_too = 1;
continue;
}
if (!strcmp(arg, "-v")) {
verbose = 1;
continue;
}
if (!strcmp(arg, "-u")) {
take_worktree_changes = 1;
continue;
}
if (!strcmp(arg, "--refresh")) {
refresh_only = 1;
continue;
}
usage(builtin_add_usage);
}
if (take_worktree_changes) {
if (read_cache() < 0)
die("index file corrupt");
add_files_to_cache(verbose, prefix, argv + i);
add_files_to_cache(verbose, prefix, argv);
goto finish;
}
if (argc <= i) {
if (argc == 0) {
fprintf(stderr, "Nothing specified, nothing added.\n");
fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
return 0;
}
pathspec = get_pathspec(prefix, argv + i);
pathspec = get_pathspec(prefix, argv);
if (refresh_only) {
refresh(verbose, pathspec);

View File

@@ -2215,9 +2215,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
argv[unk++] = arg;
}
if (!incremental)
setup_pager();
if (!blame_move_score)
blame_move_score = BLAME_DEFAULT_MOVE_SCORE;
if (!blame_copy_score)
@@ -2411,6 +2408,9 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
read_mailmap(&mailmap, ".mailmap", NULL);
if (!incremental)
setup_pager();
assign_blame(&sb, &revs, opt);
if (incremental)

View File

@@ -11,9 +11,15 @@
#include "commit.h"
#include "builtin.h"
#include "remote.h"
#include "parse-options.h"
static const char builtin_branch_usage[] =
"git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length> | --no-abbrev]]";
static const char * const builtin_branch_usage[] = {
"git-branch [options] [-r | -a]",
"git-branch [options] [-l] [-f] <branchname> [<start-point>]",
"git-branch [options] [-r] (-d | -D) <branchname>",
"git-branch [options] (-m | -M) [<oldbranch>] <newbranch>",
NULL
};
#define REF_UNKNOWN_TYPE 0x00
#define REF_LOCAL_BRANCH 0x01
@@ -142,7 +148,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
if (!force &&
!in_merge_bases(rev, &head_rev, 1)) {
error("The branch '%s' is not a strict subset of "
error("The branch '%s' is not an ancestor of "
"your current HEAD.\n"
"If you are sure you want to delete it, "
"run 'git branch -D %s'.", argv[i], argv[i]);
@@ -276,7 +282,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
commit = lookup_commit(item->sha1);
if (commit && !parse_commit(commit)) {
pretty_print_commit(CMIT_FMT_ONELINE, commit,
&subject, 0, NULL, NULL, 0);
&subject, 0, NULL, NULL, 0, 0);
sub = subject.buf;
}
printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
@@ -505,93 +511,45 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
int rename = 0, force_rename = 0;
int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
int reflog = 0, track;
int kinds = REF_LOCAL_BRANCH;
int i;
int kinds = REF_LOCAL_BRANCH, kind_remote = 0, kind_any = 0;
struct option options[] = {
OPT_GROUP("Generic options"),
OPT__VERBOSE(&verbose),
OPT_BOOLEAN( 0 , "track", &track, "set up tracking mode (see git-pull(1))"),
OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"),
OPT_BOOLEAN('r', NULL, &kind_remote, "act on remote-tracking branches"),
OPT__ABBREV(&abbrev),
OPT_GROUP("Specific git-branch actions:"),
OPT_BOOLEAN('a', NULL, &kind_any, "list both remote-tracking and local branches"),
OPT_BOOLEAN('d', NULL, &delete, "delete fully merged branch"),
OPT_BOOLEAN('D', NULL, &force_delete, "delete branch (even if not merged)"),
OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"),
OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"),
OPT_BOOLEAN('m', NULL, &rename, "move/rename a branch and its reflog"),
OPT_BOOLEAN('M', NULL, &force_rename, "move/rename a branch, even if target exists"),
OPT_END(),
};
git_config(git_branch_config);
track = branch_track;
argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (arg[0] != '-')
break;
if (!strcmp(arg, "--")) {
i++;
break;
}
if (!strcmp(arg, "--track")) {
track = 1;
continue;
}
if (!strcmp(arg, "--no-track")) {
track = 0;
continue;
}
if (!strcmp(arg, "-d")) {
delete = 1;
continue;
}
if (!strcmp(arg, "-D")) {
delete = 1;
force_delete = 1;
continue;
}
if (!strcmp(arg, "-f")) {
force_create = 1;
continue;
}
if (!strcmp(arg, "-m")) {
rename = 1;
continue;
}
if (!strcmp(arg, "-M")) {
rename = 1;
force_rename = 1;
continue;
}
if (!strcmp(arg, "-r")) {
kinds = REF_REMOTE_BRANCH;
continue;
}
if (!strcmp(arg, "-a")) {
kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH;
continue;
}
if (!strcmp(arg, "-l")) {
reflog = 1;
continue;
}
if (!prefixcmp(arg, "--no-abbrev")) {
abbrev = 0;
continue;
}
if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg + 9, NULL, 10);
if (abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
else if (abbrev > 40)
abbrev = 40;
continue;
}
if (!strcmp(arg, "-v")) {
verbose = 1;
continue;
}
if (!strcmp(arg, "--color")) {
branch_use_color = 1;
continue;
}
if (!strcmp(arg, "--no-color")) {
branch_use_color = 0;
continue;
}
usage(builtin_branch_usage);
}
delete |= force_delete;
rename |= force_rename;
if (kind_remote)
kinds = REF_REMOTE_BRANCH;
if (kind_any)
kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH;
if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
else if (abbrev > 40)
abbrev = 40;
if ((delete && rename) || (delete && force_create) ||
(rename && force_create))
usage(builtin_branch_usage);
usage_with_options(builtin_branch_usage, options);
head = resolve_ref("HEAD", head_sha1, 0, NULL);
if (!head)
@@ -599,26 +557,25 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
head = xstrdup(head);
if (!strcmp(head, "HEAD")) {
detached = 1;
}
else {
} else {
if (prefixcmp(head, "refs/heads/"))
die("HEAD not found below refs/heads!");
head += 11;
}
if (delete)
return delete_branches(argc - i, argv + i, force_delete, kinds);
else if (i == argc)
return delete_branches(argc, argv, force_delete, kinds);
else if (argc == 0)
print_ref_list(kinds, detached, verbose, abbrev);
else if (rename && (i == argc - 1))
rename_branch(head, argv[i], force_rename);
else if (rename && (i == argc - 2))
rename_branch(argv[i], argv[i + 1], force_rename);
else if (i == argc - 1 || i == argc - 2)
create_branch(argv[i], (i == argc - 2) ? argv[i+1] : head,
else if (rename && (argc == 1))
rename_branch(head, argv[0], force_rename);
else if (rename && (argc == 2))
rename_branch(argv[0], argv[1], force_rename);
else if (argc <= 2)
create_branch(argv[0], (argc == 2) ? argv[1] : head,
force_create, reflog, track);
else
usage(builtin_branch_usage);
usage_with_options(builtin_branch_usage, options);
return 0;
}

View File

@@ -6,8 +6,7 @@
#include "cache.h"
#include "builtin.h"
static const char count_objects_usage[] = "git-count-objects [-v]";
#include "parse-options.h"
static void count_objects(DIR *d, char *path, int len, int verbose,
unsigned long *loose,
@@ -71,29 +70,28 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
}
}
int cmd_count_objects(int ac, const char **av, const char *prefix)
static char const * const count_objects_usage[] = {
"git-count-objects [-v]",
NULL
};
int cmd_count_objects(int argc, const char **argv, const char *prefix)
{
int i;
int verbose = 0;
int i, verbose = 0;
const char *objdir = get_object_directory();
int len = strlen(objdir);
char *path = xmalloc(len + 50);
unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
unsigned long loose_size = 0;
struct option opts[] = {
OPT__VERBOSE(&verbose),
OPT_END(),
};
for (i = 1; i < ac; i++) {
const char *arg = av[i];
if (*arg != '-')
break;
else if (!strcmp(arg, "-v"))
verbose = 1;
else
usage(count_objects_usage);
}
argc = parse_options(argc, argv, opts, count_objects_usage, 0);
/* we do not take arguments other than flags for now */
if (i < ac)
usage(count_objects_usage);
if (argc)
usage_with_options(count_objects_usage, opts);
memcpy(path, objdir, len);
if (len && objdir[len-1] != '/')
path[len++] = '/';

View File

@@ -4,12 +4,15 @@
#include "refs.h"
#include "builtin.h"
#include "exec_cmd.h"
#include "parse-options.h"
#define SEEN (1u<<0)
#define MAX_TAGS (FLAG_BITS - 1)
static const char describe_usage[] =
"git-describe [--all] [--tags] [--abbrev=<n>] <committish>*";
static const char * const describe_usage[] = {
"git-describe [options] <committish>*",
NULL
};
static int debug; /* Display lots of verbose info */
static int all; /* Default to annotated tags only */
@@ -242,57 +245,42 @@ static void describe(const char *arg, int last_one)
int cmd_describe(int argc, const char **argv, const char *prefix)
{
int i;
int contains = 0;
struct option options[] = {
OPT_BOOLEAN(0, "contains", &contains, "find the tag that comes after the commit"),
OPT_BOOLEAN(0, "debug", &debug, "debug search strategy on stderr"),
OPT_BOOLEAN(0, "all", &all, "use any ref in .git/refs"),
OPT_BOOLEAN(0, "tags", &tags, "use any tag in .git/refs/tags"),
OPT__ABBREV(&abbrev),
OPT_INTEGER(0, "candidates", &max_candidates,
"consider <n> most recent tags (default: 10)"),
OPT_END(),
};
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (*arg != '-')
break;
else if (!strcmp(arg, "--contains"))
contains = 1;
else if (!strcmp(arg, "--debug"))
debug = 1;
else if (!strcmp(arg, "--all"))
all = 1;
else if (!strcmp(arg, "--tags"))
tags = 1;
else if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg + 9, NULL, 10);
if (abbrev != 0 && (abbrev < MINIMUM_ABBREV || 40 < abbrev))
abbrev = DEFAULT_ABBREV;
}
else if (!prefixcmp(arg, "--candidates=")) {
max_candidates = strtoul(arg + 13, NULL, 10);
if (max_candidates < 1)
max_candidates = 1;
else if (max_candidates > MAX_TAGS)
max_candidates = MAX_TAGS;
}
else
usage(describe_usage);
}
argc = parse_options(argc, argv, options, describe_usage, 0);
if (max_candidates < 1)
max_candidates = 1;
else if (max_candidates > MAX_TAGS)
max_candidates = MAX_TAGS;
save_commit_buffer = 0;
if (contains) {
const char **args = xmalloc((4 + argc - i) * sizeof(char*));
const char **args = xmalloc((4 + argc) * sizeof(char*));
args[0] = "name-rev";
args[1] = "--name-only";
args[2] = "--tags";
memcpy(args + 3, argv + i, (argc - i) * sizeof(char*));
args[3 + argc - i] = NULL;
return cmd_name_rev(3 + argc - i, args, prefix);
memcpy(args + 3, argv, argc * sizeof(char*));
args[3 + argc] = NULL;
return cmd_name_rev(3 + argc, args, prefix);
}
if (argc <= i)
if (argc == 0) {
describe("HEAD", 1);
else
while (i < argc) {
describe(argv[i], (i == argc - 1));
i++;
} else {
while (argc-- > 0) {
describe(*argv++, argc == 0);
}
}
return 0;
}

View File

@@ -131,12 +131,6 @@ static struct ref *get_ref_map(struct transport *transport,
return ref_map;
}
static void show_new(enum object_type type, unsigned char *sha1_new)
{
fprintf(stderr, " %s: %s\n", typename(type),
find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
}
static int s_update_ref(const char *action,
struct ref *ref,
int check_old)
@@ -157,34 +151,38 @@ static int s_update_ref(const char *action,
return 0;
}
#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
static int update_local_ref(struct ref *ref,
const char *note,
int verbose)
const char *remote,
int verbose,
char *display)
{
char oldh[41], newh[41];
struct commit *current = NULL, *updated;
enum object_type type;
struct branch *current_branch = branch_get(NULL);
const char *pretty_ref = ref->name + (
!prefixcmp(ref->name, "refs/heads/") ? 11 :
!prefixcmp(ref->name, "refs/tags/") ? 10 :
!prefixcmp(ref->name, "refs/remotes/") ? 13 :
0);
*display = 0;
type = sha1_object_info(ref->new_sha1, NULL);
if (type < 0)
die("object %s not found", sha1_to_hex(ref->new_sha1));
if (!*ref->name) {
/* Not storing */
if (verbose) {
fprintf(stderr, "* fetched %s\n", note);
show_new(type, ref->new_sha1);
}
if (verbose)
sprintf(display, "* branch %s -> FETCH_HEAD", remote);
return 0;
}
if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
if (verbose) {
fprintf(stderr, "* %s: same as %s\n",
ref->name, note);
show_new(type, ref->new_sha1);
}
if (verbose)
sprintf(display, "= %-*s %s -> %s", SUMMARY_WIDTH,
"[up to date]", remote, pretty_ref);
return 0;
}
@@ -196,63 +194,65 @@ static int update_local_ref(struct ref *ref,
* If this is the head, and it's not okay to update
* the head, and the old value of the head isn't empty...
*/
fprintf(stderr,
" * %s: Cannot fetch into the current branch.\n",
ref->name);
sprintf(display, "! %-*s %s -> %s (can't fetch in current branch)",
SUMMARY_WIDTH, "[rejected]", remote, pretty_ref);
return 1;
}
if (!is_null_sha1(ref->old_sha1) &&
!prefixcmp(ref->name, "refs/tags/")) {
fprintf(stderr, "* %s: updating with %s\n",
ref->name, note);
show_new(type, ref->new_sha1);
sprintf(display, "- %-*s %s -> %s",
SUMMARY_WIDTH, "[tag update]", remote, pretty_ref);
return s_update_ref("updating tag", ref, 0);
}
current = lookup_commit_reference_gently(ref->old_sha1, 1);
updated = lookup_commit_reference_gently(ref->new_sha1, 1);
if (!current || !updated) {
char *msg;
if (!strncmp(ref->name, "refs/tags/", 10))
const char *msg;
const char *what;
if (!strncmp(ref->name, "refs/tags/", 10)) {
msg = "storing tag";
else
what = "[new tag]";
}
else {
msg = "storing head";
fprintf(stderr, "* %s: storing %s\n",
ref->name, note);
show_new(type, ref->new_sha1);
what = "[new branch]";
}
sprintf(display, "* %-*s %s -> %s",
SUMMARY_WIDTH, what, remote, pretty_ref);
return s_update_ref(msg, ref, 0);
}
strcpy(oldh, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcpy(newh, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
if (in_merge_bases(current, &updated, 1)) {
fprintf(stderr, "* %s: fast forward to %s\n",
ref->name, note);
fprintf(stderr, " old..new: %s..%s\n", oldh, newh);
char quickref[83];
strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcat(quickref, "..");
strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
sprintf(display, " %-*s %s -> %s (fast forward)",
SUMMARY_WIDTH, quickref, remote, pretty_ref);
return s_update_ref("fast forward", ref, 1);
}
if (!force && !ref->force) {
fprintf(stderr,
"* %s: not updating to non-fast forward %s\n",
ref->name, note);
fprintf(stderr,
" old...new: %s...%s\n", oldh, newh);
} else if (force || ref->force) {
char quickref[84];
strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcat(quickref, "...");
strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
sprintf(display, "+ %-*s %s -> %s (forced update)",
SUMMARY_WIDTH, quickref, remote, pretty_ref);
return s_update_ref("forced-update", ref, 1);
} else {
sprintf(display, "! %-*s %s -> %s (non fast forward)",
SUMMARY_WIDTH, "[rejected]", remote, pretty_ref);
return 1;
}
fprintf(stderr,
"* %s: forcing update to non-fast forward %s\n",
ref->name, note);
fprintf(stderr, " old...new: %s...%s\n", oldh, newh);
return s_update_ref("forced-update", ref, 1);
}
static void store_updated_refs(const char *url, struct ref *ref_map)
{
FILE *fp;
struct commit *commit;
int url_len, i, note_len;
int url_len, i, note_len, shown_url = 0;
char note[1024];
const char *what, *kind;
struct ref *rm;
@@ -315,8 +315,17 @@ static void store_updated_refs(const char *url, struct ref *ref_map)
rm->merge ? "" : "not-for-merge",
note);
if (ref)
update_local_ref(ref, note, verbose);
if (ref) {
update_local_ref(ref, what, verbose, note);
if (*note) {
if (!shown_url) {
fprintf(stderr, "From %.*s\n",
url_len, url);
shown_url = 1;
}
fprintf(stderr, " %s\n", note);
}
}
}
fclose(fp);
}
@@ -376,9 +385,6 @@ 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) &&
lookup_object(ref->old_sha1)) {
fprintf(stderr, "Auto-following %s\n",
ref_name);
path_list_insert(ref_name, &new_refs);
rm = alloc_ref(strlen(ref_name) + 1);
@@ -517,7 +523,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
depth = argv[i];
continue;
}
if (!strcmp(arg, "--quiet")) {
if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) {
quiet = 1;
continue;
}

View File

@@ -7,6 +7,7 @@
#include "tree.h"
#include "blob.h"
#include "quote.h"
#include "parse-options.h"
/* Quoting styles */
#define QUOTE_NONE 0
@@ -158,17 +159,18 @@ static const char *find_next(const char *cp)
* Make sure the format string is well formed, and parse out
* the used atoms.
*/
static void verify_format(const char *format)
static int verify_format(const char *format)
{
const char *cp, *sp;
for (cp = format; *cp && (sp = find_next(cp)); ) {
const char *ep = strchr(sp, ')');
if (!ep)
die("malformatted format string %s", sp);
return error("malformatted format string %s", sp);
/* sp points at "%(" and ep points at the closing ")" */
parse_atom(sp + 2, ep);
cp = ep + 1;
}
return 0;
}
/*
@@ -800,94 +802,76 @@ static struct ref_sort *default_sort(void)
return sort;
}
int cmd_for_each_ref(int ac, const char **av, const char *prefix)
int opt_parse_sort(const struct option *opt, const char *arg, int unset)
{
struct ref_sort **sort_tail = opt->value;
struct ref_sort *s;
int len;
if (!arg) /* should --no-sort void the list ? */
return -1;
*sort_tail = s = xcalloc(1, sizeof(*s));
sort_tail = &s->next;
if (*arg == '-') {
s->reverse = 1;
arg++;
}
len = strlen(arg);
s->atom = parse_atom(arg, arg+len);
return 0;
}
static char const * const for_each_ref_usage[] = {
"git-for-each-ref [options] [<pattern>]",
NULL
};
int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
{
int i, num_refs;
const char *format = NULL;
const char *format = "%(objectname) %(objecttype)\t%(refname)";
struct ref_sort *sort = NULL, **sort_tail = &sort;
int maxcount = 0;
int quote_style = -1; /* unspecified yet */
int maxcount = 0, quote_style;
int quote_shell = 0, quote_perl = 0, quote_python = 0, quote_tcl = 0;
struct refinfo **refs;
struct grab_ref_cbdata cbdata;
for (i = 1; i < ac; i++) {
const char *arg = av[i];
if (arg[0] != '-')
break;
if (!strcmp(arg, "--")) {
i++;
break;
}
if (!prefixcmp(arg, "--format=")) {
if (format)
die("more than one --format?");
format = arg + 9;
continue;
}
if (!strcmp(arg, "-s") || !strcmp(arg, "--shell") ) {
if (0 <= quote_style)
die("more than one quoting style?");
quote_style = QUOTE_SHELL;
continue;
}
if (!strcmp(arg, "-p") || !strcmp(arg, "--perl") ) {
if (0 <= quote_style)
die("more than one quoting style?");
quote_style = QUOTE_PERL;
continue;
}
if (!strcmp(arg, "--python") ) {
if (0 <= quote_style)
die("more than one quoting style?");
quote_style = QUOTE_PYTHON;
continue;
}
if (!strcmp(arg, "--tcl") ) {
if (0 <= quote_style)
die("more than one quoting style?");
quote_style = QUOTE_TCL;
continue;
}
if (!prefixcmp(arg, "--count=")) {
if (maxcount)
die("more than one --count?");
maxcount = atoi(arg + 8);
if (maxcount <= 0)
die("The number %s did not parse", arg);
continue;
}
if (!prefixcmp(arg, "--sort=")) {
struct ref_sort *s = xcalloc(1, sizeof(*s));
int len;
struct option opts[] = {
OPT_BOOLEAN('s', "shell", &quote_shell, "quote placeholders suitably for shells"),
OPT_BOOLEAN('p', "perl", &quote_perl, "quote placeholders suitably for perl"),
OPT_BOOLEAN( 0 , "python", &quote_python, "quote placeholders suitably for python"),
OPT_BOOLEAN( 0 , "tcl", &quote_tcl, "quote placeholders suitably for tcl"),
s->next = NULL;
*sort_tail = s;
sort_tail = &s->next;
OPT_GROUP(""),
OPT_INTEGER( 0 , "count", &maxcount, "show only <n> matched refs"),
OPT_STRING( 0 , "format", &format, "format", "format to use for the output"),
OPT_CALLBACK(0 , "sort", &sort_tail, "key",
"field name to sort on", &opt_parse_sort),
OPT_END(),
};
arg += 7;
if (*arg == '-') {
s->reverse = 1;
arg++;
}
len = strlen(arg);
sort->atom = parse_atom(arg, arg+len);
continue;
}
break;
parse_options(argc, argv, opts, for_each_ref_usage, 0);
if (maxcount < 0) {
error("invalid --count argument: `%d'", maxcount);
usage_with_options(for_each_ref_usage, opts);
}
if (quote_style < 0)
quote_style = QUOTE_NONE;
if (quote_shell + quote_perl + quote_python + quote_tcl > 1) {
error("more than one quoting style ?");
usage_with_options(for_each_ref_usage, opts);
}
if (verify_format(format))
usage_with_options(for_each_ref_usage, opts);
quote_style = QUOTE_SHELL * quote_shell + QUOTE_PERL * quote_perl +
QUOTE_PYTHON * quote_python + QUOTE_TCL * quote_tcl;
if (!sort)
sort = default_sort();
sort_atom_limit = used_atom_cnt;
if (!format)
format = "%(objectname) %(objecttype)\t%(refname)";
verify_format(format);
memset(&cbdata, 0, sizeof(cbdata));
cbdata.grab_pattern = av + i;
cbdata.grab_pattern = argv;
for_each_ref(grab_single_ref, &cbdata);
refs = cbdata.grab_array;
num_refs = cbdata.grab_cnt;

View File

@@ -8,6 +8,7 @@
#include "pack.h"
#include "cache-tree.h"
#include "tree-walk.h"
#include "parse-options.h"
#define REACHABLE 0x0001
#define SEEN 0x0002
@@ -666,9 +667,24 @@ static int fsck_cache_tree(struct cache_tree *it)
return err;
}
static const char fsck_usage[] =
"git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] "
"[--strict] [--verbose] <head-sha1>*]";
static char const * const fsck_usage[] = {
"git-fsck [options] [<object>...]",
NULL
};
static struct option fsck_opts[] = {
OPT__VERBOSE(&verbose),
OPT_BOOLEAN(0, "unreachable", &show_unreachable, "show unreachable objects"),
OPT_BOOLEAN(0, "tags", &show_tags, "report tags"),
OPT_BOOLEAN(0, "root", &show_root, "report root nodes"),
OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"),
OPT_BOOLEAN(0, "reflogs", &include_reflogs, "make reflogs head nodes (default)"),
OPT_BOOLEAN(0, "full", &check_full, "also consider alternate objects"),
OPT_BOOLEAN(0, "strict", &check_strict, "enable more strict checking"),
OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
"write dangling objects in .git/lost-found"),
OPT_END(),
};
int cmd_fsck(int argc, const char **argv, const char *prefix)
{
@@ -677,49 +693,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
track_object_refs = 1;
errors_found = 0;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--unreachable")) {
show_unreachable = 1;
continue;
}
if (!strcmp(arg, "--tags")) {
show_tags = 1;
continue;
}
if (!strcmp(arg, "--root")) {
show_root = 1;
continue;
}
if (!strcmp(arg, "--cache")) {
keep_cache_objects = 1;
continue;
}
if (!strcmp(arg, "--no-reflogs")) {
include_reflogs = 0;
continue;
}
if (!strcmp(arg, "--full")) {
check_full = 1;
continue;
}
if (!strcmp(arg, "--strict")) {
check_strict = 1;
continue;
}
if (!strcmp(arg, "--verbose")) {
verbose = 1;
continue;
}
if (!strcmp(arg, "--lost-found")) {
check_full = 1;
include_reflogs = 0;
write_lost_and_found = 1;
continue;
}
if (*arg == '-')
usage(fsck_usage);
argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0);
if (write_lost_and_found) {
check_full = 1;
include_reflogs = 0;
}
fsck_head_link();
@@ -741,22 +718,18 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
verify_pack(p, 0);
for (p = packed_git; p; p = p->next) {
uint32_t i, num;
uint32_t j, num;
if (open_pack_index(p))
continue;
num = p->num_objects;
for (i = 0; i < num; i++)
fsck_sha1(nth_packed_object_sha1(p, i));
for (j = 0; j < num; j++)
fsck_sha1(nth_packed_object_sha1(p, j));
}
}
heads = 0;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (*arg == '-')
continue;
if (!get_sha1(arg, head_sha1)) {
struct object *obj = lookup_object(head_sha1);
@@ -783,7 +756,6 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
}
if (keep_cache_objects) {
int i;
read_cache();
for (i = 0; i < active_nr; i++) {
unsigned int mode;

View File

@@ -12,11 +12,15 @@
#include "builtin.h"
#include "cache.h"
#include "parse-options.h"
#include "run-command.h"
#define FAILED_RUN "failed to run %s"
static const char builtin_gc_usage[] = "git-gc [--prune] [--aggressive]";
static const char * const builtin_gc_usage[] = {
"git-gc [options]",
NULL
};
static int pack_refs = 1;
static int aggressive_window = -1;
@@ -165,38 +169,34 @@ static int need_to_gc(void)
int cmd_gc(int argc, const char **argv, const char *prefix)
{
int i;
int prune = 0;
int aggressive = 0;
int auto_gc = 0;
char buf[80];
struct option builtin_gc_options[] = {
OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced loose objects"),
OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"),
OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"),
OPT_END()
};
git_config(gc_config);
if (pack_refs < 0)
pack_refs = !is_bare_repository();
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--prune")) {
prune = 1;
continue;
argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);
if (argc > 0)
usage_with_options(builtin_gc_usage, builtin_gc_options);
if (aggressive) {
append_option(argv_repack, "-f", MAX_ADD);
if (aggressive_window > 0) {
sprintf(buf, "--window=%d", aggressive_window);
append_option(argv_repack, buf, MAX_ADD);
}
if (!strcmp(arg, "--aggressive")) {
append_option(argv_repack, "-f", MAX_ADD);
if (aggressive_window > 0) {
sprintf(buf, "--window=%d", aggressive_window);
append_option(argv_repack, buf, MAX_ADD);
}
continue;
}
if (!strcmp(arg, "--auto")) {
auto_gc = 1;
continue;
}
break;
}
if (i != argc)
usage(builtin_gc_usage);
if (auto_gc) {
/*

View File

@@ -787,7 +787,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
struct strbuf buf;
strbuf_init(&buf, 0);
pretty_print_commit(CMIT_FMT_ONELINE, commit,
&buf, 0, NULL, NULL, 0);
&buf, 0, NULL, NULL, 0, 0);
printf("%c %s %s\n", sign,
sha1_to_hex(commit->object.sha1), buf.buf);
strbuf_release(&buf);

View File

@@ -915,6 +915,7 @@ static void handle_info(void)
static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
const char *msg, const char *patch)
{
int peek;
keep_subject = ks;
metainfo_charset = encoding;
fin = in;
@@ -935,6 +936,11 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
do {
peek = fgetc(in);
} while (isspace(peek));
ungetc(peek, in);
/* process the email header */
while (read_one_header_line(line, sizeof(line), fin))
check_header(line, sizeof(line), p_hdr_data, 1);

View File

@@ -164,6 +164,7 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
{
char name[PATH_MAX];
int ret = -1;
int peek;
FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r");
int file_done = 0;
@@ -173,6 +174,11 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
goto out;
}
do {
peek = fgetc(f);
} while (isspace(peek));
ungetc(peek, f);
if (fgets(buf, sizeof(buf), f) == NULL) {
/* empty stdin is OK */
if (f != stdin) {

View File

@@ -8,9 +8,12 @@
#include "dir.h"
#include "cache-tree.h"
#include "path-list.h"
#include "parse-options.h"
static const char builtin_mv_usage[] =
"git-mv [-n] [-f] (<source> <destination> | [-k] <source>... <destination>)";
static const char * const builtin_mv_usage[] = {
"git-mv [options] <source>... <destination>",
NULL
};
static const char **copy_pathspec(const char *prefix, const char **pathspec,
int count, int base_name)
@@ -61,8 +64,14 @@ static struct lock_file lock_file;
int cmd_mv(int argc, const char **argv, const char *prefix)
{
int i, newfd, count;
int i, newfd;
int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
struct option builtin_mv_options[] = {
OPT__DRY_RUN(&show_only),
OPT_BOOLEAN('f', NULL, &force, "force move/rename even if target exists"),
OPT_BOOLEAN('k', NULL, &ignore_errors, "skip move/rename errors"),
OPT_END(),
};
const char **source, **destination, **dest_path;
enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;
struct stat st;
@@ -78,52 +87,29 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die("index file corrupt");
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
argc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0);
if (--argc < 1)
usage_with_options(builtin_mv_usage, builtin_mv_options);
if (arg[0] != '-')
break;
if (!strcmp(arg, "--")) {
i++;
break;
}
if (!strcmp(arg, "-n")) {
show_only = 1;
continue;
}
if (!strcmp(arg, "-f")) {
force = 1;
continue;
}
if (!strcmp(arg, "-k")) {
ignore_errors = 1;
continue;
}
usage(builtin_mv_usage);
}
count = argc - i - 1;
if (count < 1)
usage(builtin_mv_usage);
source = copy_pathspec(prefix, argv + i, count, 0);
modes = xcalloc(count, sizeof(enum update_mode));
dest_path = copy_pathspec(prefix, argv + argc - 1, 1, 0);
source = copy_pathspec(prefix, argv, argc, 0);
modes = xcalloc(argc, sizeof(enum update_mode));
dest_path = copy_pathspec(prefix, argv + argc, 1, 0);
if (dest_path[0][0] == '\0')
/* special case: "." was normalized to "" */
destination = copy_pathspec(dest_path[0], argv + i, count, 1);
destination = copy_pathspec(dest_path[0], argv, argc, 1);
else if (!lstat(dest_path[0], &st) &&
S_ISDIR(st.st_mode)) {
dest_path[0] = add_slash(dest_path[0]);
destination = copy_pathspec(dest_path[0], argv + i, count, 1);
destination = copy_pathspec(dest_path[0], argv, argc, 1);
} else {
if (count != 1)
usage(builtin_mv_usage);
if (argc != 1)
usage_with_options(builtin_mv_usage, builtin_mv_options);
destination = dest_path;
}
/* Checking */
for (i = 0; i < count; i++) {
for (i = 0; i < argc; i++) {
const char *src = source[i], *dst = destination[i];
int length, src_is_dir;
const char *bad = NULL;
@@ -167,13 +153,13 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (last - first > 0) {
source = xrealloc(source,
(count + last - first)
(argc + last - first)
* sizeof(char *));
destination = xrealloc(destination,
(count + last - first)
(argc + last - first)
* sizeof(char *));
modes = xrealloc(modes,
(count + last - first)
(argc + last - first)
* sizeof(enum update_mode));
}
@@ -183,13 +169,13 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
for (j = 0; j < last - first; j++) {
const char *path =
active_cache[first + j]->name;
source[count + j] = path;
destination[count + j] =
source[argc + j] = path;
destination[argc + j] =
prefix_path(dst, dst_len,
path + length);
modes[count + j] = INDEX;
modes[argc + j] = INDEX;
}
count += last - first;
argc += last - first;
}
} else if (lstat(dst, &st) == 0) {
bad = "destination exists";
@@ -216,12 +202,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (bad) {
if (ignore_errors) {
if (--count > 0) {
if (--argc > 0) {
memmove(source + i, source + i + 1,
(count - i) * sizeof(char *));
(argc - i) * sizeof(char *));
memmove(destination + i,
destination + i + 1,
(count - i) * sizeof(char *));
(argc - i) * sizeof(char *));
}
} else
die ("%s, source=%s, destination=%s",
@@ -229,7 +215,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
}
}
for (i = 0; i < count; i++) {
for (i = 0; i < argc; i++) {
const char *src = source[i], *dst = destination[i];
enum update_mode mode = modes[i];
if (show_only || verbose)
@@ -253,7 +239,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
path_list_insert(dst, &added);
}
if (show_only) {
if (show_only) {
show_list("Changed : ", &changed);
show_list("Adding : ", &added);
show_list("Deleting : ", &deleted);

View File

@@ -3,12 +3,10 @@
#include "commit.h"
#include "tag.h"
#include "refs.h"
#include "parse-options.h"
#define CUTOFF_DATE_SLOP 86400 /* one day */
static const char name_rev_usage[] =
"git-name-rev [--tags | --refs=<pattern>] ( --all | --stdin | committish [committish...] )\n";
typedef struct rev_name {
const char *tip_name;
int generation;
@@ -153,51 +151,41 @@ static const char* get_rev_name(struct object *o)
}
}
static char const * const name_rev_usage[] = {
"git-name-rev [options] ( --all | --stdin | <commit>... )",
NULL
};
int cmd_name_rev(int argc, const char **argv, const char *prefix)
{
struct object_array revs = { 0, 0, NULL };
int as_is = 0, all = 0, transform_stdin = 0;
int all = 0, transform_stdin = 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)"),
OPT_BOOLEAN(0, "tags", &data.tags_only, "only use tags to name the commits"),
OPT_STRING(0, "refs", &data.ref_filter, "pattern",
"only use refs matching <pattern>"),
OPT_GROUP(""),
OPT_BOOLEAN(0, "all", &all, "list all commits reachable from all refs"),
OPT_BOOLEAN(0, "stdin", &transform_stdin, "read from stdin"),
OPT_END(),
};
git_config(git_default_config);
argc = parse_options(argc, argv, opts, name_rev_usage, 0);
if (!!all + !!transform_stdin + !!argc > 1) {
error("Specify either a list, or --all, not both!");
usage_with_options(name_rev_usage, opts);
}
if (all || transform_stdin)
cutoff = 0;
if (argc < 2)
usage(name_rev_usage);
for (--argc, ++argv; argc; --argc, ++argv) {
for (; argc; argc--, argv++) {
unsigned char sha1[20];
struct object *o;
struct commit *commit;
if (!as_is && (*argv)[0] == '-') {
if (!strcmp(*argv, "--")) {
as_is = 1;
continue;
} else if (!strcmp(*argv, "--name-only")) {
data.name_only = 1;
continue;
} else if (!strcmp(*argv, "--tags")) {
data.tags_only = 1;
continue;
} else if (!prefixcmp(*argv, "--refs=")) {
data.ref_filter = *argv + 7;
continue;
} else if (!strcmp(*argv, "--all")) {
if (argc > 1)
die("Specify either a list, or --all, not both!");
all = 1;
cutoff = 0;
continue;
} else if (!strcmp(*argv, "--stdin")) {
if (argc > 1)
die("Specify either a list, or --stdin, not both!");
transform_stdin = 1;
cutoff = 0;
continue;
}
usage(name_rev_usage);
}
if (get_sha1(*argv, sha1)) {
fprintf(stderr, "Could not get sha1 for %s. Skipping.\n",
*argv);
@@ -212,10 +200,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
}
commit = (struct commit *)o;
if (cutoff > commit->date)
cutoff = commit->date;
add_object_array((struct object *)commit, *argv, &revs);
}

View File

@@ -57,7 +57,7 @@ struct object_entry {
* nice "minimum seek" order.
*/
static struct object_entry *objects;
static struct object_entry **written_list;
static struct pack_idx_entry **written_list;
static uint32_t nr_objects, nr_alloc, nr_result, nr_written;
static int non_empty;
@@ -65,8 +65,6 @@ static int no_reuse_delta, no_reuse_object, keep_unreachable;
static int local;
static int incremental;
static int allow_ofs_delta;
static const char *pack_tmp_name, *idx_tmp_name;
static char tmpname[PATH_MAX];
static const char *base_name;
static int progress = 1;
static int window = 10;
@@ -75,7 +73,7 @@ static int depth = 50;
static int delta_search_threads = 1;
static int pack_to_stdout;
static int num_preferred_base;
static struct progress progress_state;
static struct progress *progress_state;
static int pack_compression_level = Z_DEFAULT_COMPRESSION;
static int pack_compression_seen;
@@ -579,7 +577,7 @@ static off_t write_one(struct sha1file *f,
e->idx.offset = 0;
return 0;
}
written_list[nr_written++] = e;
written_list[nr_written++] = &e->idx;
/* make sure off_t is sufficiently large not to wrap */
if (offset > offset + size)
@@ -587,12 +585,6 @@ static off_t write_one(struct sha1file *f,
return offset + size;
}
static int open_object_dir_tmp(const char *path)
{
snprintf(tmpname, sizeof(tmpname), "%s/%s", get_object_directory(), path);
return xmkstemp(tmpname);
}
/* forward declaration for write_pack_file */
static int adjust_perm(const char *path, mode_t mode);
@@ -606,16 +598,21 @@ static void write_pack_file(void)
uint32_t nr_remaining = nr_result;
if (do_progress)
start_progress(&progress_state, "Writing %u objects...", "", nr_result);
written_list = xmalloc(nr_objects * sizeof(struct object_entry *));
progress_state = start_progress("Writing objects", nr_result);
written_list = xmalloc(nr_objects * sizeof(*written_list));
do {
unsigned char sha1[20];
char *pack_tmp_name = NULL;
if (pack_to_stdout) {
f = sha1fd(1, "<stdout>");
f = sha1fd_throughput(1, "<stdout>", progress_state);
} else {
int fd = open_object_dir_tmp("tmp_pack_XXXXXX");
char tmpname[PATH_MAX];
int fd;
snprintf(tmpname, sizeof(tmpname),
"%s/tmp_pack_XXXXXX", get_object_directory());
fd = xmkstemp(tmpname);
pack_tmp_name = xstrdup(tmpname);
f = sha1fd(fd, pack_tmp_name);
}
@@ -632,8 +629,7 @@ static void write_pack_file(void)
if (!offset_one)
break;
offset = offset_one;
if (do_progress)
display_progress(&progress_state, written);
display_progress(progress_state, written);
}
/*
@@ -643,19 +639,20 @@ static void write_pack_file(void)
if (pack_to_stdout || nr_written == nr_remaining) {
sha1close(f, sha1, 1);
} else {
sha1close(f, sha1, 0);
fixup_pack_header_footer(f->fd, sha1, pack_tmp_name, nr_written);
close(f->fd);
int fd = sha1close(f, NULL, 0);
fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written);
close(fd);
}
if (!pack_to_stdout) {
mode_t mode = umask(0);
char *idx_tmp_name, tmpname[PATH_MAX];
umask(mode);
mode = 0444 & ~mode;
idx_tmp_name = write_idx_file(NULL,
(struct pack_idx_entry **) written_list, nr_written, sha1);
idx_tmp_name = write_idx_file(NULL, written_list,
nr_written, sha1);
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
base_name, sha1_to_hex(sha1));
if (adjust_perm(pack_tmp_name, mode))
@@ -672,19 +669,20 @@ static void write_pack_file(void)
if (rename(idx_tmp_name, tmpname))
die("unable to rename temporary index file: %s",
strerror(errno));
free(idx_tmp_name);
free(pack_tmp_name);
puts(sha1_to_hex(sha1));
}
/* mark written objects as written to previous pack */
for (j = 0; j < nr_written; j++) {
written_list[j]->idx.offset = (off_t)-1;
written_list[j]->offset = (off_t)-1;
}
nr_remaining -= nr_written;
} while (nr_remaining && i < nr_objects);
free(written_list);
if (do_progress)
stop_progress(&progress_state);
stop_progress(&progress_state);
if (written != nr_result)
die("wrote %u objects while expecting %u", written, nr_result);
/*
@@ -852,8 +850,7 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
else
object_ix[-1 - ix] = nr_objects;
if (progress)
display_progress(&progress_state, nr_objects);
display_progress(progress_state, nr_objects);
if (name && no_try_delta(name))
entry->no_try_delta = 1;
@@ -1516,8 +1513,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size,
progress_lock();
(*processed)++;
if (progress)
display_progress(&progress_state, *processed);
display_progress(progress_state, *processed);
progress_unlock();
/*
@@ -1714,16 +1710,14 @@ static void prepare_pack(int window, int depth)
delta_list[n++] = entry;
}
if (nr_deltas) {
if (nr_deltas && n > 1) {
unsigned nr_done = 0;
if (progress)
start_progress(&progress_state,
"Deltifying %u objects...", "",
nr_deltas);
progress_state = start_progress("Compressing objects",
nr_deltas);
qsort(delta_list, n, sizeof(*delta_list), type_size_sort);
ll_find_deltas(delta_list, n, window+1, depth, &nr_done);
if (progress)
stop_progress(&progress_state);
stop_progress(&progress_state);
if (nr_done != nr_deltas)
die("inconsistency with delta count");
}
@@ -1773,6 +1767,12 @@ static int git_pack_config(const char *k, const char *v)
#endif
return 0;
}
if (!strcmp(k, "pack.indexversion")) {
pack_idx_default_version = git_config_int(k, v);
if (pack_idx_default_version > 2)
die("bad pack.indexversion=%d", pack_idx_default_version);
return 0;
}
return git_default_config(k, v);
}
@@ -2135,23 +2135,17 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
prepare_packed_git();
if (progress)
start_progress(&progress_state, "Generating pack...",
"Counting objects: ", 0);
progress_state = start_progress("Counting objects", 0);
if (!use_internal_rev_list)
read_object_list_from_stdin();
else {
rp_av[rp_ac] = NULL;
get_object_list(rp_ac, rp_av);
}
if (progress) {
stop_progress(&progress_state);
fprintf(stderr, "Done counting %u objects.\n", nr_objects);
}
stop_progress(&progress_state);
if (non_empty && !nr_result)
return 0;
if (progress && (nr_objects != nr_result))
fprintf(stderr, "Result has %u objects.\n", nr_result);
if (nr_result)
prepare_pack(window, depth);
write_pack_file();

View File

@@ -3,9 +3,7 @@
#include "refs.h"
#include "object.h"
#include "tag.h"
static const char builtin_pack_refs_usage[] =
"git-pack-refs [--all] [--prune | --no-prune]";
#include "parse-options.h"
struct ref_to_prune {
struct ref_to_prune *next;
@@ -117,31 +115,26 @@ static int pack_refs(unsigned int flags)
return 0;
}
static char const * const pack_refs_usage[] = {
"git-pack-refs [options]",
NULL
};
int cmd_pack_refs(int argc, const char **argv, const char *prefix)
{
int i;
unsigned int flags;
flags = PACK_REFS_PRUNE;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--prune")) {
flags |= PACK_REFS_PRUNE; /* now the default */
continue;
}
if (!strcmp(arg, "--no-prune")) {
flags &= ~PACK_REFS_PRUNE;
continue;
}
if (!strcmp(arg, "--all")) {
flags |= PACK_REFS_ALL;
continue;
}
/* perhaps other parameters later... */
break;
}
if (i != argc)
usage(builtin_pack_refs_usage);
int all = 0, prune = 1;
unsigned int flags = 0;
struct option opts[] = {
OPT_BOOLEAN(0, "all", &all, "pack everything"),
OPT_BOOLEAN(0, "prune", &prune, "prune loose refs (default)"),
OPT_END(),
};
if (parse_options(argc, argv, opts, pack_refs_usage, 0))
usage_with_options(pack_refs_usage, opts);
if (prune)
flags |= PACK_REFS_PRUNE;
if (all)
flags |= PACK_REFS_ALL;
return pack_refs(flags);
}

View File

@@ -1,5 +1,6 @@
#include "builtin.h"
#include "cache.h"
#include "progress.h"
static const char prune_packed_usage[] =
"git-prune-packed [-n] [-q]";
@@ -7,6 +8,8 @@ static const char prune_packed_usage[] =
#define DRY_RUN 01
#define VERBOSE 02
static struct progress *progress;
static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
{
struct dirent *de;
@@ -27,6 +30,7 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
printf("rm -f %s\n", pathname);
else if (unlink(pathname) < 0)
error("unable to unlink %s", pathname);
display_progress(progress, i + 1);
}
pathname[len] = 0;
rmdir(pathname);
@@ -39,6 +43,10 @@ void prune_packed_objects(int opts)
const char *dir = get_object_directory();
int len = strlen(dir);
if (opts == VERBOSE)
progress = start_progress_delay("Removing duplicate objects",
256, 95, 2);
if (len > PATH_MAX - 42)
die("impossible object directory");
memcpy(pathname, dir, len);
@@ -49,16 +57,12 @@ void prune_packed_objects(int opts)
sprintf(pathname + len, "%02x/", i);
d = opendir(pathname);
if (opts == VERBOSE && (d || i == 255))
fprintf(stderr, "Removing unused objects %d%%...\015",
((i+1) * 100) / 256);
if (!d)
continue;
prune_dir(i, d, pathname, len + 3, opts);
closedir(d);
}
if (opts == VERBOSE)
fprintf(stderr, "\nDone.\n");
stop_progress(&progress);
}
int cmd_prune_packed(int argc, const char **argv, const char *prefix)

View File

@@ -113,10 +113,17 @@ static int update_index_refresh(void)
return run_command_v_opt(argv_update_index, RUN_GIT_CMD);
}
struct update_cb_data {
int index_fd;
struct lock_file *lock;
int exit_code;
};
static void update_index_from_diff(struct diff_queue_struct *q,
struct diff_options *opt, void *data)
{
int i;
struct update_cb_data *cb = data;
/* do_diff_cache() mangled the index */
discard_cache();
@@ -133,29 +140,34 @@ static void update_index_from_diff(struct diff_queue_struct *q,
} else
remove_file_from_cache(one->path);
}
cb->exit_code = write_cache(cb->index_fd, active_cache, active_nr) ||
close(cb->index_fd) ||
commit_locked_index(cb->lock);
}
static int read_from_tree(const char *prefix, const char **argv,
unsigned char *tree_sha1)
{
struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
int index_fd;
struct diff_options opt;
struct update_cb_data cb;
memset(&opt, 0, sizeof(opt));
diff_tree_setup_paths(get_pathspec(prefix, (const char **)argv), &opt);
opt.output_format = DIFF_FORMAT_CALLBACK;
opt.format_callback = update_index_from_diff;
opt.format_callback_data = &cb;
index_fd = hold_locked_index(lock, 1);
cb.lock = xcalloc(1, sizeof(struct lock_file));
cb.index_fd = hold_locked_index(cb.lock, 1);
cb.exit_code = 0;
read_cache();
if (do_diff_cache(tree_sha1, &opt))
return 1;
diffcore_std(&opt);
diff_flush(&opt);
return write_cache(index_fd, active_cache, active_nr) ||
close(index_fd) ||
commit_locked_index(lock);
return cb.exit_code;
}
static void prepend_reflog_action(const char *action, char *buf, size_t size)

View File

@@ -86,7 +86,8 @@ static void show_commit(struct commit *commit)
struct strbuf buf;
strbuf_init(&buf, 0);
pretty_print_commit(revs.commit_format, commit,
&buf, revs.abbrev, NULL, NULL, revs.date_mode);
&buf, revs.abbrev, NULL, NULL,
revs.date_mode, 0);
if (buf.len)
printf("%s%c", buf.buf, hdr_termination);
strbuf_release(&buf);

View File

@@ -7,6 +7,7 @@
#include "run-command.h"
#include "exec_cmd.h"
#include "utf8.h"
#include "parse-options.h"
/*
* This implements the builtins revert and cherry-pick.
@@ -19,51 +20,44 @@
* Copyright (c) 2005 Junio C Hamano
*/
static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] <commit-ish>";
static const char * const revert_usage[] = {
"git-revert [options] <commit-ish>",
NULL
};
static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] <commit-ish>";
static const char * const cherry_pick_usage[] = {
"git-cherry-pick [options] <commit-ish>",
NULL
};
static int edit;
static int replay;
static int edit, no_replay, no_commit, needed_deref, mainline;
static enum { REVERT, CHERRY_PICK } action;
static int no_commit;
static struct commit *commit;
static int needed_deref;
static const char *me;
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
static void parse_options(int argc, const char **argv)
static void parse_args(int argc, const char **argv)
{
const char *usage_str = action == REVERT ?
revert_usage : cherry_pick_usage;
const char * const * usage_str =
action == REVERT ? revert_usage : cherry_pick_usage;
unsigned char sha1[20];
const char *arg;
int i;
int noop;
struct option options[] = {
OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
OPT_BOOLEAN('x', NULL, &no_replay, "append commit name when cherry-picking"),
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
OPT_END(),
};
if (argc < 2)
usage(usage_str);
if (parse_options(argc, argv, options, usage_str, 0) != 1)
usage_with_options(usage_str, options);
arg = argv[0];
for (i = 1; i < argc; i++) {
arg = argv[i];
if (arg[0] != '-')
break;
if (!strcmp(arg, "-n") || !strcmp(arg, "--no-commit"))
no_commit = 1;
else if (!strcmp(arg, "-e") || !strcmp(arg, "--edit"))
edit = 1;
else if (!strcmp(arg, "--no-edit"))
edit = 0;
else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-"
"to-expose-my-private-commit-object-name"))
replay = 0;
else if (strcmp(arg, "-r"))
usage(usage_str);
}
if (i != argc - 1)
usage(usage_str);
arg = argv[argc - 1];
if (get_sha1(arg, sha1))
die ("Cannot find '%s'", arg);
commit = (struct commit *)parse_object(sha1);
@@ -234,7 +228,7 @@ static int merge_recursive(const char *base_sha1,
static int revert_or_cherry_pick(int argc, const char **argv)
{
unsigned char head[20];
struct commit *base, *next;
struct commit *base, *next, *parent;
int i;
char *oneline, *reencoded_message = NULL;
const char *message, *encoding;
@@ -243,10 +237,10 @@ static int revert_or_cherry_pick(int argc, const char **argv)
git_config(git_default_config);
me = action == REVERT ? "revert" : "cherry-pick";
setenv(GIT_REFLOG_ACTION, me, 0);
parse_options(argc, argv);
parse_args(argc, argv);
/* this is copied from the shell script, but it's never triggered... */
if (action == REVERT && replay)
if (action == REVERT && !no_replay)
die("revert is incompatible with replay");
if (no_commit) {
@@ -269,8 +263,29 @@ static int revert_or_cherry_pick(int argc, const char **argv)
if (!commit->parents)
die ("Cannot %s a root commit", me);
if (commit->parents->next)
die ("Cannot %s a multi-parent commit.", me);
if (commit->parents->next) {
/* Reverting or cherry-picking a merge commit */
int cnt;
struct commit_list *p;
if (!mainline)
die("Commit %s is a merge but no -m option was given.",
sha1_to_hex(commit->object.sha1));
for (cnt = 1, p = commit->parents;
cnt != mainline && p;
cnt++)
p = p->next;
if (cnt != mainline || !p)
die("Commit %s does not have parent %d",
sha1_to_hex(commit->object.sha1), mainline);
parent = p->item;
} else if (0 < mainline)
die("Mainline was specified but commit %s is not a merge.",
sha1_to_hex(commit->object.sha1));
else
parent = commit->parents->item;
if (!(message = commit->buffer))
die ("Cannot get commit message for %s",
sha1_to_hex(commit->object.sha1));
@@ -299,18 +314,18 @@ static int revert_or_cherry_pick(int argc, const char **argv)
char *oneline_body = strchr(oneline, ' ');
base = commit;
next = commit->parents->item;
next = parent;
add_to_msg("Revert \"");
add_to_msg(oneline_body + 1);
add_to_msg("\"\n\nThis reverts commit ");
add_to_msg(sha1_to_hex(commit->object.sha1));
add_to_msg(".\n");
} else {
base = commit->parents->item;
base = parent;
next = commit;
set_author_ident_env(message);
add_message_to_msg(message);
if (!replay) {
if (no_replay) {
add_to_msg("(cherry picked from commit ");
add_to_msg(sha1_to_hex(commit->object.sha1));
add_to_msg(")\n");
@@ -388,13 +403,14 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
{
if (isatty(0))
edit = 1;
no_replay = 1;
action = REVERT;
return revert_or_cherry_pick(argc, argv);
}
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
{
replay = 1;
no_replay = 0;
action = CHERRY_PICK;
return revert_or_cherry_pick(argc, argv);
}

View File

@@ -8,9 +8,12 @@
#include "dir.h"
#include "cache-tree.h"
#include "tree-walk.h"
#include "parse-options.h"
static const char builtin_rm_usage[] =
"git-rm [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...";
static const char * const builtin_rm_usage[] = {
"git-rm [options] [--] <file>...",
NULL
};
static struct {
int nr, alloc;
@@ -121,11 +124,23 @@ static int check_local_mod(unsigned char *head, int index_only)
static struct lock_file lock_file;
static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
static int ignore_unmatch = 0;
static struct option builtin_rm_options[] = {
OPT__DRY_RUN(&show_only),
OPT__QUIET(&quiet),
OPT_BOOLEAN( 0 , "cached", &index_only, "only remove from the index"),
OPT_BOOLEAN('f', NULL, &force, "override the up-to-date check"),
OPT_BOOLEAN('r', NULL, &recursive, "allow recursive removal"),
OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
"exit with a zero status even if nothing matched"),
OPT_END(),
};
int cmd_rm(int argc, const char **argv, const char *prefix)
{
int i, newfd;
int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
int ignore_unmatch = 0;
const char **pathspec;
char *seen;
@@ -136,34 +151,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die("index file corrupt");
for (i = 1 ; i < argc ; i++) {
const char *arg = argv[i];
argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);
if (!argc)
usage_with_options(builtin_rm_usage, builtin_rm_options);
if (*arg != '-')
break;
else if (!strcmp(arg, "--")) {
i++;
break;
}
else if (!strcmp(arg, "-n"))
show_only = 1;
else if (!strcmp(arg, "--cached"))
index_only = 1;
else if (!strcmp(arg, "-f"))
force = 1;
else if (!strcmp(arg, "-r"))
recursive = 1;
else if (!strcmp(arg, "--quiet"))
quiet = 1;
else if (!strcmp(arg, "--ignore-unmatch"))
ignore_unmatch = 1;
else
usage(builtin_rm_usage);
}
if (argc <= i)
usage(builtin_rm_usage);
pathspec = get_pathspec(prefix, argv + i);
pathspec = get_pathspec(prefix, argv);
seen = NULL;
for (i = 0; pathspec[i] ; i++)
/* nothing */;

View File

@@ -266,7 +266,7 @@ static void show_one_commit(struct commit *commit, int no_name)
strbuf_init(&pretty, 0);
if (commit->object.parsed) {
pretty_print_commit(CMIT_FMT_ONELINE, commit,
&pretty, 0, NULL, NULL, 0);
&pretty, 0, NULL, NULL, 0, 0);
pretty_str = pretty.buf;
}
if (!prefixcmp(pretty_str, "[PATCH] "))

View File

@@ -1,9 +1,12 @@
#include "builtin.h"
#include "cache.h"
#include "refs.h"
#include "parse-options.h"
static const char git_symbolic_ref_usage[] =
"git-symbolic-ref [-q] [-m <reason>] name [ref]";
static const char * const git_symbolic_ref_usage[] = {
"git-symbolic-ref [options] name [ref]",
NULL
};
static void check_symref(const char *HEAD, int quiet)
{
@@ -26,44 +29,25 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
{
int quiet = 0;
const char *msg = NULL;
struct option options[] = {
OPT__QUIET(&quiet),
OPT_STRING('m', NULL, &msg, "reason", "reason of the update"),
OPT_END(),
};
git_config(git_default_config);
while (1 < argc) {
const char *arg = argv[1];
if (arg[0] != '-')
break;
else if (!strcmp("-q", arg))
quiet = 1;
else if (!strcmp("-m", arg)) {
argc--;
argv++;
if (argc <= 1)
break;
msg = argv[1];
if (!*msg)
die("Refusing to perform update with empty message");
}
else if (!strcmp("--", arg)) {
argc--;
argv++;
break;
}
else
die("unknown option %s", arg);
argc--;
argv++;
}
argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0);
if (msg &&!*msg)
die("Refusing to perform update with empty message");
switch (argc) {
case 2:
check_symref(argv[1], quiet);
case 1:
check_symref(argv[0], quiet);
break;
case 3:
create_symref(argv[1], argv[2], msg);
case 2:
create_symref(argv[0], argv[1], msg);
break;
default:
usage(git_symbolic_ref_usage);
usage_with_options(git_symbolic_ref_usage, options);
}
return 0;
}

View File

@@ -311,7 +311,7 @@ static void unpack_one(unsigned nr)
static void unpack_all(void)
{
int i;
struct progress progress;
struct progress *progress = NULL;
struct pack_header *hdr = fill(sizeof(struct pack_header));
unsigned nr_objects = ntohl(hdr->hdr_entries);
@@ -322,15 +322,13 @@ static void unpack_all(void)
use(sizeof(struct pack_header));
if (!quiet)
start_progress(&progress, "Unpacking %u objects...", "", nr_objects);
progress = start_progress("Unpacking objects", nr_objects);
obj_list = xmalloc(nr_objects * sizeof(*obj_list));
for (i = 0; i < nr_objects; i++) {
unpack_one(i);
if (!quiet)
display_progress(&progress, i + 1);
display_progress(progress, i + 1);
}
if (!quiet)
stop_progress(&progress);
stop_progress(&progress);
if (delta_list)
die("unresolved deltas left after unpacking");

View File

@@ -1,59 +1,44 @@
#include "cache.h"
#include "refs.h"
#include "builtin.h"
#include "parse-options.h"
static const char git_update_ref_usage[] =
"git-update-ref [-m <reason>] (-d <refname> <value> | [--no-deref] <refname> <value> [<oldval>])";
static const char * const git_update_ref_usage[] = {
"git-update-ref [options] -d <refname> <oldval>",
"git-update-ref [options] <refname> <newval> [<oldval>]",
NULL
};
int cmd_update_ref(int argc, const char **argv, const char *prefix)
{
const char *refname=NULL, *value=NULL, *oldval=NULL, *msg=NULL;
const char *refname, *value, *oldval, *msg=NULL;
unsigned char sha1[20], oldsha1[20];
int i, delete, ref_flags;
int delete = 0, no_deref = 0;
struct option options[] = {
OPT_STRING( 'm', NULL, &msg, "reason", "reason of the update"),
OPT_BOOLEAN('d', NULL, &delete, "deletes the reference"),
OPT_BOOLEAN( 0 , "no-deref", &no_deref,
"update <refname> not the one it points to"),
OPT_END(),
};
delete = 0;
ref_flags = 0;
git_config(git_default_config);
argc = parse_options(argc, argv, options, git_update_ref_usage, 0);
if (msg && !*msg)
die("Refusing to perform update with empty message.");
for (i = 1; i < argc; i++) {
if (!strcmp("-m", argv[i])) {
if (i+1 >= argc)
usage(git_update_ref_usage);
msg = argv[++i];
if (!*msg)
die("Refusing to perform update with empty message.");
continue;
}
if (!strcmp("-d", argv[i])) {
delete = 1;
continue;
}
if (!strcmp("--no-deref", argv[i])) {
ref_flags |= REF_NODEREF;
continue;
}
if (!refname) {
refname = argv[i];
continue;
}
if (!value) {
value = argv[i];
continue;
}
if (!oldval) {
oldval = argv[i];
continue;
}
}
if (!refname || !value)
usage(git_update_ref_usage);
if (argc < 2 || argc > 3)
usage_with_options(git_update_ref_usage, options);
refname = argv[0];
value = argv[1];
oldval = argv[2];
if (get_sha1(value, sha1))
die("%s: not a valid SHA1", value);
if (delete) {
if (oldval)
usage(git_update_ref_usage);
usage_with_options(git_update_ref_usage, options);
return delete_ref(refname, sha1);
}
@@ -62,5 +47,5 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
die("%s: not a valid old SHA1", oldval);
return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
ref_flags, DIE_ON_ERR);
no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
}

View File

@@ -479,7 +479,7 @@ static int get_one_line(const char *msg)
}
/* High bit set, or ISO-2022-INT */
static int non_ascii(int ch)
int non_ascii(int ch)
{
ch = (ch & 0xff);
return ((ch & 0x80) || (ch == 0x1b));
@@ -1046,12 +1046,11 @@ static void pp_remainder(enum cmit_fmt fmt,
void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
struct strbuf *sb, int abbrev,
const char *subject, const char *after_subject,
enum date_mode dmode)
enum date_mode dmode, int plain_non_ascii)
{
unsigned long beginning_of_body;
int indent = 4;
const char *msg = commit->buffer;
int plain_non_ascii = 0;
char *reencoded;
const char *encoding;

View File

@@ -61,13 +61,15 @@ enum cmit_fmt {
CMIT_FMT_UNSPECIFIED,
};
extern int non_ascii(int);
extern enum cmit_fmt get_commit_format(const char *arg);
extern void format_commit_message(const struct commit *commit,
const void *format, struct strbuf *sb);
extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
struct strbuf *,
int abbrev, const char *subject,
const char *after_subject, enum date_mode);
const char *after_subject, enum date_mode,
int non_ascii_present);
/** Removes the first commit from a list sorted by date, and adds all
* of its parents.

View File

@@ -8,6 +8,7 @@
* able to verify hasn't been messed with afterwards.
*/
#include "cache.h"
#include "progress.h"
#include "csum-file.h"
static void sha1flush(struct sha1file *f, unsigned int count)
@@ -17,6 +18,7 @@ static void sha1flush(struct sha1file *f, unsigned int count)
for (;;) {
int ret = xwrite(f->fd, buf, count);
if (ret > 0) {
display_throughput(f->tp, ret);
buf = (char *) buf + ret;
count -= ret;
if (count)
@@ -31,22 +33,27 @@ static void sha1flush(struct sha1file *f, unsigned int count)
int sha1close(struct sha1file *f, unsigned char *result, int final)
{
int fd;
unsigned offset = f->offset;
if (offset) {
SHA1_Update(&f->ctx, f->buffer, offset);
sha1flush(f, offset);
f->offset = 0;
}
if (!final)
return 0; /* only want to flush (no checksum write, no close) */
SHA1_Final(f->buffer, &f->ctx);
if (result)
hashcpy(result, f->buffer);
sha1flush(f, 20);
if (close(f->fd))
die("%s: sha1 file error on close (%s)", f->name, strerror(errno));
if (final) {
/* write checksum and close fd */
SHA1_Final(f->buffer, &f->ctx);
if (result)
hashcpy(result, f->buffer);
sha1flush(f, 20);
if (close(f->fd))
die("%s: sha1 file error on close (%s)",
f->name, strerror(errno));
fd = 0;
} else
fd = f->fd;
free(f);
return 0;
return fd;
}
int sha1write(struct sha1file *f, void *buf, unsigned int count)
@@ -74,6 +81,11 @@ int sha1write(struct sha1file *f, void *buf, unsigned int count)
}
struct sha1file *sha1fd(int fd, const char *name)
{
return sha1fd_throughput(fd, name, NULL);
}
struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp)
{
struct sha1file *f;
unsigned len;
@@ -89,6 +101,7 @@ struct sha1file *sha1fd(int fd, const char *name)
f->fd = fd;
f->error = 0;
f->offset = 0;
f->tp = tp;
f->do_crc = 0;
SHA1_Init(&f->ctx);
return f;

View File

@@ -1,11 +1,14 @@
#ifndef CSUM_FILE_H
#define CSUM_FILE_H
struct progress;
/* A SHA1-protected file */
struct sha1file {
int fd, error;
unsigned int offset, namelen;
SHA_CTX ctx;
struct progress *tp;
char name[PATH_MAX];
int do_crc;
uint32_t crc32;
@@ -13,6 +16,7 @@ struct sha1file {
};
extern struct sha1file *sha1fd(int fd, const char *name);
extern struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp);
extern int sha1close(struct sha1file *, unsigned char *, int);
extern int sha1write(struct sha1file *, void *, unsigned int);
extern void crc32_begin(struct sha1file *);

View File

@@ -51,7 +51,7 @@ case $(uname -s) in
esac
usage() {
die "Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] <repo> [<dir>]"
die "Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] [--] <repo> [<dir>]"
}
get_repo_base() {
@@ -197,6 +197,9 @@ while
*,--depth)
shift
depth="--depth=$1";;
*,--)
shift
break ;;
*,-*) usage ;;
*) break ;;
esac

View File

@@ -394,6 +394,19 @@ static inline int strtoul_ui(char const *s, int base, unsigned int *result)
return 0;
}
static inline int strtol_i(char const *s, int base, int *result)
{
long ul;
char *p;
errno = 0;
ul = strtol(s, &p, base);
if (errno || *p || p == s || (int) ul != ul)
return -1;
*result = ul;
return 0;
}
#ifdef __MINGW32__
#ifndef S_ISLNK

View File

@@ -818,6 +818,7 @@ while (<CVS>) {
$state = 4;
} elsif ($state == 4 and s/^Branch:\s+//) {
s/\s+$//;
tr/_/\./ if ( $opt_u );
s/[\/]/$opt_s/g;
$branch = $_;
$state = 5;

View File

@@ -83,9 +83,6 @@ for name in $names ; do
fullbases="$fullbases pack-$name"
chmod a-w "$PACKTMP-$name.pack"
chmod a-w "$PACKTMP-$name.idx"
if test "$quiet" != '-q'; then
echo "Pack pack-$name created."
fi
mkdir -p "$PACKDIR" || exit
for sfx in pack idx

View File

@@ -252,7 +252,7 @@ Usage: $0 <command> [options] [arguments]\n
next if $cmd && $cmd ne $_;
next if /^multi-/; # don't show deprecated commands
print $fd ' ',pack('A17',$_),$cmd{$_}->[1],"\n";
foreach (keys %{$cmd{$_}->[2]}) {
foreach (sort keys %{$cmd{$_}->[2]}) {
# mixed-case options are for .git/config only
next if /[A-Z]/ && /^[a-z]+$/i;
# prints out arguments as they should be passed:

View File

@@ -611,6 +611,15 @@ sub href(%) {
);
my %mapping = @mapping;
if ($params{-replay}) {
while (my ($name, $symbol) = each %mapping) {
if (!exists $params{$name}) {
# to allow for multivalued params we use arrayref form
$params{$name} = [ $cgi->param($symbol) ];
}
}
}
$params{'project'} = $project unless exists $params{'project'};
my ($use_pathinfo) = gitweb_check_feature('pathinfo');
@@ -1423,20 +1432,121 @@ sub git_get_type {
return $type;
}
# repository configuration
our $config_file = '';
our %config;
# store multiple values for single key as anonymous array reference
# single values stored directly in the hash, not as [ <value> ]
sub hash_set_multi {
my ($hash, $key, $value) = @_;
if (!exists $hash->{$key}) {
$hash->{$key} = $value;
} elsif (!ref $hash->{$key}) {
$hash->{$key} = [ $hash->{$key}, $value ];
} else {
push @{$hash->{$key}}, $value;
}
}
# return hash of git project configuration
# optionally limited to some section, e.g. 'gitweb'
sub git_parse_project_config {
my $section_regexp = shift;
my %config;
local $/ = "\0";
open my $fh, "-|", git_cmd(), "config", '-z', '-l',
or return;
while (my $keyval = <$fh>) {
chomp $keyval;
my ($key, $value) = split(/\n/, $keyval, 2);
hash_set_multi(\%config, $key, $value)
if (!defined $section_regexp || $key =~ /^(?:$section_regexp)\./o);
}
close $fh;
return %config;
}
# convert config value to boolean, 'true' or 'false'
# no value, number > 0, 'true' and 'yes' values are true
# rest of values are treated as false (never as error)
sub config_to_bool {
my $val = shift;
# strip leading and trailing whitespace
$val =~ s/^\s+//;
$val =~ s/\s+$//;
return (!defined $val || # section.key
($val =~ /^\d+$/ && $val) || # section.key = 1
($val =~ /^(?:true|yes)$/i)); # section.key = true
}
# convert config value to simple decimal number
# an optional value suffix of 'k', 'm', or 'g' will cause the value
# to be multiplied by 1024, 1048576, or 1073741824
sub config_to_int {
my $val = shift;
# strip leading and trailing whitespace
$val =~ s/^\s+//;
$val =~ s/\s+$//;
if (my ($num, $unit) = ($val =~ /^([0-9]*)([kmg])$/i)) {
$unit = lc($unit);
# unknown unit is treated as 1
return $num * ($unit eq 'g' ? 1073741824 :
$unit eq 'm' ? 1048576 :
$unit eq 'k' ? 1024 : 1);
}
return $val;
}
# convert config value to array reference, if needed
sub config_to_multi {
my $val = shift;
return ref($val) ? $val : [ $val ];
}
sub git_get_project_config {
my ($key, $type) = @_;
# key sanity check
return unless ($key);
$key =~ s/^gitweb\.//;
return if ($key =~ m/\W/);
my @x = (git_cmd(), 'config');
if (defined $type) { push @x, $type; }
push @x, "--get";
push @x, "gitweb.$key";
my $val = qx(@x);
chomp $val;
return ($val);
# type sanity check
if (defined $type) {
$type =~ s/^--//;
$type = undef
unless ($type eq 'bool' || $type eq 'int');
}
# get config
if (!defined $config_file ||
$config_file ne "$git_dir/config") {
%config = git_parse_project_config('gitweb');
$config_file = "$git_dir/config";
}
# ensure given type
if (!defined $type) {
return $config{"gitweb.$key"};
} elsif ($type eq 'bool') {
# backward compatibility: 'git config --bool' returns true/false
return config_to_bool($config{"gitweb.$key"}) ? 'true' : 'false';
} elsif ($type eq 'int') {
return config_to_int($config{"gitweb.$key"});
}
return $config{"gitweb.$key"};
}
# get hash of given path at given ref
@@ -1496,7 +1606,9 @@ sub git_get_path_by_hash {
sub git_get_project_description {
my $path = shift;
open my $fd, "$projectroot/$path/description" or return undef;
$git_dir = "$projectroot/$path";
open my $fd, "$projectroot/$path/description"
or return git_get_project_config('description');
my $descr = <$fd>;
close $fd;
if (defined $descr) {
@@ -1508,7 +1620,11 @@ sub git_get_project_description {
sub git_get_project_url_list {
my $path = shift;
open my $fd, "$projectroot/$path/cloneurl" or return;
$git_dir = "$projectroot/$path";
open my $fd, "$projectroot/$path/cloneurl"
or return wantarray ?
@{ config_to_multi(git_get_project_config('url')) } :
config_to_multi(git_get_project_config('url'));
my @git_project_url_list = map { chomp; $_ } <$fd>;
close $fd;
@@ -1990,12 +2106,12 @@ sub parse_difftree_raw_line {
$res{'to_mode'} = $2;
$res{'from_id'} = $3;
$res{'to_id'} = $4;
$res{'status'} = $5;
$res{'status'} = $res{'status_str'} = $5;
$res{'similarity'} = $6;
if ($res{'status'} eq 'R' || $res{'status'} eq 'C') { # renamed or copied
($res{'from_file'}, $res{'to_file'}) = map { unquote($_) } split("\t", $7);
} else {
$res{'file'} = unquote($7);
$res{'from_file'} = $res{'to_file'} = $res{'file'} = unquote($7);
}
}
# '::100755 100755 100755 60e79ca1b01bc8b057abe17ddab484699a7f5fdb 94067cc5f73388f33722d52ae02f44692bc07490 94067cc5f73388f33722d52ae02f44692bc07490 MR git-gui/git-gui.sh'
@@ -2006,6 +2122,7 @@ sub parse_difftree_raw_line {
$res{'to_mode'} = pop @{$res{'from_mode'}};
$res{'from_id'} = [ split(' ', $3) ];
$res{'to_id'} = pop @{$res{'from_id'}};
$res{'status_str'} = $4;
$res{'status'} = [ split('', $4) ];
$res{'to_file'} = unquote($5);
}
@@ -2062,7 +2179,10 @@ sub parse_from_to_diffinfo {
fill_from_file_info($diffinfo, @parents)
unless exists $diffinfo->{'from_file'};
for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {
$from->{'file'}[$i] = $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'};
$from->{'file'}[$i] =
defined $diffinfo->{'from_file'}[$i] ?
$diffinfo->{'from_file'}[$i] :
$diffinfo->{'to_file'};
if ($diffinfo->{'status'}[$i] ne "A") { # not new (added) file
$from->{'href'}[$i] = href(action=>"blob",
hash_base=>$parents[$i],
@@ -2074,7 +2194,7 @@ sub parse_from_to_diffinfo {
}
} else {
# ordinary (not combined) diff
$from->{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'};
$from->{'file'} = $diffinfo->{'from_file'};
if ($diffinfo->{'status'} ne "A") { # not new (added) file
$from->{'href'} = href(action=>"blob", hash_base=>$hash_parent,
hash=>$diffinfo->{'from_id'},
@@ -2084,7 +2204,7 @@ sub parse_from_to_diffinfo {
}
}
$to->{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'};
$to->{'file'} = $diffinfo->{'to_file'};
if (!is_deleted($diffinfo)) { # file exists in result
$to->{'href'} = href(action=>"blob", hash_base=>$hash,
hash=>$diffinfo->{'to_id'},
@@ -2505,7 +2625,7 @@ sub format_paging_nav {
if ($page > 0) {
$paging_nav .= " &sdot; " .
$cgi->a({-href => href(action=>$action, hash=>$hash, page=>$page-1),
$cgi->a({-href => href(-replay=>1, page=>$page-1),
-accesskey => "p", -title => "Alt-p"}, "prev");
} else {
$paging_nav .= " &sdot; prev";
@@ -2513,7 +2633,7 @@ sub format_paging_nav {
if ($nrevs >= (100 * ($page+1)-1)) {
$paging_nav .= " &sdot; " .
$cgi->a({-href => href(action=>$action, hash=>$hash, page=>$page+1),
$cgi->a({-href => href(-replay=>1, page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
} else {
$paging_nav .= " &sdot; next";
@@ -2818,7 +2938,7 @@ sub fill_from_file_info {
sub is_deleted {
my $diffinfo = shift;
return $diffinfo->{'to_id'} eq ('0' x 40);
return $diffinfo->{'status_str'} =~ /D/;
}
# does patch correspond to [previous] difftree raw line
@@ -2829,7 +2949,7 @@ sub is_patch_split {
my ($diffinfo, $patchinfo) = @_;
return defined $diffinfo && defined $patchinfo
&& ($diffinfo->{'to_file'} || $diffinfo->{'file'}) eq $patchinfo->{'to_file'};
&& $diffinfo->{'to_file'} eq $patchinfo->{'to_file'};
}
@@ -3898,11 +4018,11 @@ sub git_blame2 {
or die_error(undef, "Open git-blame failed");
git_header_html();
my $formats_nav =
$cgi->a({-href => href(action=>"blob", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)},
$cgi->a({-href => href(action=>"blob", -replay=>1)},
"blob") .
" | " .
$cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)},
"history") .
$cgi->a({-href => href(action=>"history", -replay=>1)},
"history") .
" | " .
$cgi->a({-href => href(action=>"blame", file_name=>$file_name)},
"HEAD");
@@ -4178,18 +4298,15 @@ sub git_blob {
if (defined $file_name) {
if ($have_blame) {
$formats_nav .=
$cgi->a({-href => href(action=>"blame", hash_base=>$hash_base,
hash=>$hash, file_name=>$file_name)},
$cgi->a({-href => href(action=>"blame", -replay=>1)},
"blame") .
" | ";
}
$formats_nav .=
$cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
hash=>$hash, file_name=>$file_name)},
$cgi->a({-href => href(action=>"history", -replay=>1)},
"history") .
" | " .
$cgi->a({-href => href(action=>"blob_plain",
hash=>$hash, file_name=>$file_name)},
$cgi->a({-href => href(action=>"blob_plain", -replay=>1)},
"raw") .
" | " .
$cgi->a({-href => href(action=>"blob",
@@ -4197,7 +4314,8 @@ sub git_blob {
"HEAD");
} else {
$formats_nav .=
$cgi->a({-href => href(action=>"blob_plain", hash=>$hash)}, "raw");
$cgi->a({-href => href(action=>"blob_plain", -replay=>1)},
"raw");
}
git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
@@ -4260,8 +4378,7 @@ sub git_tree {
my @views_nav = ();
if (defined $file_name) {
push @views_nav,
$cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
hash=>$hash, file_name=>$file_name)},
$cgi->a({-href => href(action=>"history", -replay=>1)},
"history"),
$cgi->a({-href => href(action=>"tree",
hash_base=>"HEAD", file_name=>$file_name)},
@@ -4435,7 +4552,7 @@ sub git_log {
}
if ($#commitlist >= 100) {
print "<div class=\"page_nav\">\n";
print $cgi->a({-href => href(action=>"log", hash=>$hash, page=>$page+1),
print $cgi->a({-href => href(-replay=>1, page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
print "</div>\n";
}
@@ -4667,8 +4784,8 @@ sub git_blobdiff {
}
%diffinfo = parse_difftree_raw_line($difftree[0]);
$file_parent ||= $diffinfo{'from_file'} || $file_name || $diffinfo{'file'};
$file_name ||= $diffinfo{'to_file'} || $diffinfo{'file'};
$file_parent ||= $diffinfo{'from_file'} || $file_name;
$file_name ||= $diffinfo{'to_file'};
$hash_parent ||= $diffinfo{'from_id'};
$hash ||= $diffinfo{'to_id'};
@@ -4729,10 +4846,7 @@ sub git_blobdiff {
# header
if ($format eq 'html') {
my $formats_nav =
$cgi->a({-href => href(action=>"blobdiff_plain",
hash=>$hash, hash_parent=>$hash_parent,
hash_base=>$hash_base, hash_parent_base=>$hash_parent_base,
file_name=>$file_name, file_parent=>$file_parent)},
$cgi->a({-href => href(action=>"blobdiff_plain", -replay=>1)},
"raw");
git_header_html(undef, $expires);
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
@@ -4806,8 +4920,7 @@ sub git_commitdiff {
my $formats_nav;
if ($format eq 'html') {
$formats_nav =
$cgi->a({-href => href(action=>"commitdiff_plain",
hash=>$hash, hash_parent=>$hash_parent)},
$cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)},
"raw");
if (defined $hash_parent &&
@@ -5002,27 +5115,20 @@ sub git_history {
file_name=>$file_name)},
"first");
$paging_nav .= " &sdot; " .
$cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base,
file_name=>$file_name, page=>$page-1),
$cgi->a({-href => href(-replay=>1, page=>$page-1),
-accesskey => "p", -title => "Alt-p"}, "prev");
} else {
$paging_nav .= "first";
$paging_nav .= " &sdot; prev";
}
if ($#commitlist >= 100) {
$paging_nav .= " &sdot; " .
$cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base,
file_name=>$file_name, page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
} else {
$paging_nav .= " &sdot; next";
}
my $next_link = '';
if ($#commitlist >= 100) {
$next_link =
$cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base,
file_name=>$file_name, page=>$page+1),
$cgi->a({-href => href(-replay=>1, page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
$paging_nav .= " &sdot; $next_link";
} else {
$paging_nav .= " &sdot; next";
}
git_header_html();
@@ -5092,30 +5198,23 @@ sub git_search {
searchtext=>$searchtext, searchtype=>$searchtype)},
"first");
$paging_nav .= " &sdot; " .
$cgi->a({-href => href(action=>"search", hash=>$hash,
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page-1),
$cgi->a({-href => href(-replay=>1, page=>$page-1),
-accesskey => "p", -title => "Alt-p"}, "prev");
} else {
$paging_nav .= "first";
$paging_nav .= " &sdot; prev";
}
if ($#commitlist >= 100) {
$paging_nav .= " &sdot; " .
$cgi->a({-href => href(action=>"search", hash=>$hash,
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
} else {
$paging_nav .= " &sdot; next";
}
my $next_link = '';
if ($#commitlist >= 100) {
$next_link =
$cgi->a({-href => href(action=>"search", hash=>$hash,
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page+1),
$cgi->a({-href => href(-replay=>1, page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
$paging_nav .= " &sdot; $next_link";
} else {
$paging_nav .= " &sdot; next";
}
if ($#commitlist >= 100) {
}
git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav);
@@ -5314,7 +5413,7 @@ sub git_shortlog {
my $next_link = '';
if ($#commitlist >= 100) {
$next_link =
$cgi->a({-href => href(action=>"shortlog", hash=>$hash, page=>$page+1),
$cgi->a({-href => href(-replay=>1, page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
}

View File

@@ -2241,7 +2241,11 @@ static int delete_remote_branch(char *pattern, int force)
/* Remote branch must be an ancestor of remote HEAD */
if (!verify_merge_base(head_sha1, remote_ref->old_sha1)) {
return error("The branch '%s' is not a strict subset of your current HEAD.\nIf you are sure you want to delete it, run:\n\t'git http-push -D %s %s'", remote_ref->name, remote->url, pattern);
return error("The branch '%s' is not an ancestor "
"of your current HEAD.\n"
"If you are sure you want to delete it,"
" run:\n\t'git http-push -D %s %s'",
remote_ref->name, remote->url, pattern);
}
}
@@ -2417,16 +2421,17 @@ int main(int argc, char **argv)
if (!has_sha1_file(ref->old_sha1) ||
!ref_newer(ref->peer_ref->new_sha1,
ref->old_sha1)) {
/* We do not have the remote ref, or
/*
* We do not have the remote ref, or
* we know that the remote ref is not
* an ancestor of what we are trying to
* push. Either way this can be losing
* commits at the remote end and likely
* we were not up to date to begin with.
*/
error("remote '%s' is not a strict "
"subset of local ref '%s'. "
"maybe you are not up-to-date and "
error("remote '%s' is not an ancestor of\n"
"local '%s'.\n"
"Maybe you are not up-to-date and "
"need to pull first?",
ref->name,
ref->peer_ref->name);

View File

@@ -46,7 +46,7 @@ static int nr_resolved_deltas;
static int from_stdin;
static int verbose;
static struct progress progress;
static struct progress *progress;
/* We always read in 4kB chunks. */
static unsigned char input_buffer[4096];
@@ -87,6 +87,8 @@ static void *fill(int min)
die("early EOF");
die("read error on input: %s", strerror(errno));
}
if (from_stdin)
display_throughput(progress, ret);
input_len += ret;
} while (input_len < min);
return input_buffer;
@@ -106,7 +108,7 @@ static void use(int bytes)
consumed_bytes += bytes;
}
static const char *open_pack_file(const char *pack_name)
static char *open_pack_file(char *pack_name)
{
if (from_stdin) {
input_fd = 0;
@@ -406,7 +408,9 @@ static void parse_pack_objects(unsigned char *sha1)
* - remember base (SHA1 or offset) for all deltas.
*/
if (verbose)
start_progress(&progress, "Indexing %u objects...", "", nr_objects);
progress = start_progress(
from_stdin ? "Receiving objects" : "Indexing objects",
nr_objects);
for (i = 0; i < nr_objects; i++) {
struct object_entry *obj = &objects[i];
data = unpack_raw_entry(obj, &delta->base);
@@ -418,12 +422,10 @@ static void parse_pack_objects(unsigned char *sha1)
} else
sha1_object(data, obj->size, obj->type, obj->idx.sha1);
free(data);
if (verbose)
display_progress(&progress, i+1);
display_progress(progress, i+1);
}
objects[i].idx.offset = consumed_bytes;
if (verbose)
stop_progress(&progress);
stop_progress(&progress);
/* Check pack integrity */
flush();
@@ -455,7 +457,7 @@ static void parse_pack_objects(unsigned char *sha1)
* for some more deltas.
*/
if (verbose)
start_progress(&progress, "Resolving %u deltas...", "", nr_deltas);
progress = start_progress("Resolving deltas", nr_deltas);
for (i = 0; i < nr_objects; i++) {
struct object_entry *obj = &objects[i];
union delta_base base;
@@ -486,8 +488,7 @@ static void parse_pack_objects(unsigned char *sha1)
obj->size, obj->type);
}
free(data);
if (verbose)
display_progress(&progress, nr_resolved_deltas);
display_progress(progress, nr_resolved_deltas);
}
}
@@ -594,8 +595,7 @@ static void fix_unresolved_deltas(int nr_unresolved)
die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
append_obj_to_pack(d->base.sha1, data, size, type);
free(data);
if (verbose)
display_progress(&progress, nr_resolved_deltas);
display_progress(progress, nr_resolved_deltas);
}
free(sorted_by_pos);
}
@@ -683,18 +683,31 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
}
}
static int git_index_pack_config(const char *k, const char *v)
{
if (!strcmp(k, "pack.indexversion")) {
pack_idx_default_version = git_config_int(k, v);
if (pack_idx_default_version > 2)
die("bad pack.indexversion=%d", pack_idx_default_version);
return 0;
}
return git_default_config(k, v);
}
int main(int argc, char **argv)
{
int i, fix_thin_pack = 0;
const char *curr_pack, *pack_name = NULL;
const char *curr_index, *index_name = NULL;
char *curr_pack, *pack_name = NULL;
char *curr_index, *index_name = NULL;
const char *keep_name = NULL, *keep_msg = NULL;
char *index_name_buf = NULL, *keep_name_buf = NULL;
struct pack_idx_entry **idx_objects;
unsigned char sha1[20];
git_config(git_index_pack_config);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
char *arg = argv[i];
if (*arg == '-') {
if (!strcmp(arg, "--stdin")) {
@@ -774,8 +787,7 @@ int main(int argc, char **argv)
deltas = xmalloc(nr_objects * sizeof(struct delta_entry));
parse_pack_objects(sha1);
if (nr_deltas == nr_resolved_deltas) {
if (verbose)
stop_progress(&progress);
stop_progress(&progress);
/* Flush remaining pack final 20-byte SHA1. */
flush();
} else {
@@ -788,11 +800,10 @@ int main(int argc, char **argv)
(nr_objects + nr_unresolved + 1)
* sizeof(*objects));
fix_unresolved_deltas(nr_unresolved);
if (verbose) {
stop_progress(&progress);
stop_progress(&progress);
if (verbose)
fprintf(stderr, "%d objects were added to complete this thin pack.\n",
nr_objects - nr_objects_initial);
}
fixup_pack_header_footer(output_fd, sha1,
curr_pack, nr_objects);
}
@@ -815,6 +826,10 @@ int main(int argc, char **argv)
free(objects);
free(index_name_buf);
free(keep_name_buf);
if (pack_name == NULL)
free(curr_pack);
if (index_name == NULL)
free(curr_index);
return 0;
}

View File

@@ -125,6 +125,18 @@ static unsigned int digits_in_number(unsigned int number)
return result;
}
static int has_non_ascii(const char *s)
{
int ch;
if (!s)
return 0;
while ((ch = *s++) != '\0') {
if (non_ascii(ch))
return 1;
}
return 0;
}
void show_log(struct rev_info *opt, const char *sep)
{
struct strbuf msgbuf;
@@ -273,7 +285,8 @@ void show_log(struct rev_info *opt, const char *sep)
*/
strbuf_init(&msgbuf, 0);
pretty_print_commit(opt->commit_format, commit, &msgbuf,
abbrev, subject, extra_headers, opt->date_mode);
abbrev, subject, extra_headers, opt->date_mode,
has_non_ascii(opt->add_signoff));
if (opt->add_signoff)
append_signoff(&msgbuf, opt->add_signoff);

View File

@@ -17,7 +17,8 @@ static int sha1_compare(const void *_a, const void *_b)
* the SHA1 hash of sorted object names. The objects array passed in
* will be sorted by SHA1 on exit.
*/
const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1)
char *write_idx_file(char *index_name, struct pack_idx_entry **objects,
int nr_objects, unsigned char *sha1)
{
struct sha1file *f;
struct pack_idx_entry **sorted_by_sha, **list, **last;

2
pack.h
View File

@@ -55,7 +55,7 @@ struct pack_idx_entry {
off_t offset;
};
extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);
extern char *write_idx_file(char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);
extern int verify_pack(struct packed_git *, int);
extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t);

322
parse-options.c Normal file
View File

@@ -0,0 +1,322 @@
#include "git-compat-util.h"
#include "parse-options.h"
#define OPT_SHORT 1
#define OPT_UNSET 2
struct optparse_t {
const char **argv;
int argc;
const char *opt;
};
static inline const char *get_arg(struct optparse_t *p)
{
if (p->opt) {
const char *res = p->opt;
p->opt = NULL;
return res;
}
p->argc--;
return *++p->argv;
}
static inline const char *skip_prefix(const char *str, const char *prefix)
{
size_t len = strlen(prefix);
return strncmp(str, prefix, len) ? NULL : str + len;
}
static int opterror(const struct option *opt, const char *reason, int flags)
{
if (flags & OPT_SHORT)
return error("switch `%c' %s", opt->short_name, reason);
if (flags & OPT_UNSET)
return error("option `no-%s' %s", opt->long_name, reason);
return error("option `%s' %s", opt->long_name, reason);
}
static int get_value(struct optparse_t *p,
const struct option *opt, int flags)
{
const char *s, *arg;
arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL);
if (p->opt && (flags & OPT_UNSET))
return opterror(opt, "takes no value", flags);
switch (opt->type) {
case OPTION_BOOLEAN:
if (!(flags & OPT_SHORT) && p->opt)
return opterror(opt, "takes no value", flags);
if (flags & OPT_UNSET)
*(int *)opt->value = 0;
else
(*(int *)opt->value)++;
return 0;
case OPTION_STRING:
if (flags & OPT_UNSET) {
*(const char **)opt->value = (const char *)NULL;
return 0;
}
if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-')) {
*(const char **)opt->value = (const char *)opt->defval;
return 0;
}
if (!arg)
return opterror(opt, "requires a value", flags);
*(const char **)opt->value = get_arg(p);
return 0;
case OPTION_CALLBACK:
if (flags & OPT_UNSET)
return (*opt->callback)(opt, NULL, 1);
if (opt->flags & PARSE_OPT_NOARG) {
if (p->opt && !(flags & OPT_SHORT))
return opterror(opt, "takes no value", flags);
return (*opt->callback)(opt, NULL, 0);
}
if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-'))
return (*opt->callback)(opt, NULL, 0);
if (!arg)
return opterror(opt, "requires a value", flags);
return (*opt->callback)(opt, get_arg(p), 0);
case OPTION_INTEGER:
if (flags & OPT_UNSET) {
*(int *)opt->value = 0;
return 0;
}
if (opt->flags & PARSE_OPT_OPTARG && (!arg || !isdigit(*arg))) {
*(int *)opt->value = opt->defval;
return 0;
}
if (!arg)
return opterror(opt, "requires a value", flags);
*(int *)opt->value = strtol(get_arg(p), (char **)&s, 10);
if (*s)
return opterror(opt, "expects a numerical value", flags);
return 0;
default:
die("should not happen, someone must be hit on the forehead");
}
}
static int parse_short_opt(struct optparse_t *p, const struct option *options)
{
for (; options->type != OPTION_END; options++) {
if (options->short_name == *p->opt) {
p->opt = p->opt[1] ? p->opt + 1 : NULL;
return get_value(p, options, OPT_SHORT);
}
}
return error("unknown switch `%c'", *p->opt);
}
static int parse_long_opt(struct optparse_t *p, const char *arg,
const struct option *options)
{
const char *arg_end = strchr(arg, '=');
const struct option *abbrev_option = NULL;
int abbrev_flags = 0;
if (!arg_end)
arg_end = arg + strlen(arg);
for (; options->type != OPTION_END; options++) {
const char *rest;
int flags = 0;
if (!options->long_name)
continue;
rest = skip_prefix(arg, options->long_name);
if (!rest) {
/* abbreviated? */
if (!strncmp(options->long_name, arg, arg_end - arg)) {
is_abbreviated:
if (abbrev_option)
return error("Ambiguous option: %s "
"(could be --%s%s or --%s%s)",
arg,
(flags & OPT_UNSET) ?
"no-" : "",
options->long_name,
(abbrev_flags & OPT_UNSET) ?
"no-" : "",
abbrev_option->long_name);
if (!(flags & OPT_UNSET) && *arg_end)
p->opt = arg_end + 1;
abbrev_option = options;
abbrev_flags = flags;
continue;
}
/* negated and abbreviated very much? */
if (!prefixcmp("no-", arg)) {
flags |= OPT_UNSET;
goto is_abbreviated;
}
/* negated? */
if (strncmp(arg, "no-", 3))
continue;
flags |= OPT_UNSET;
rest = skip_prefix(arg + 3, options->long_name);
/* abbreviated and negated? */
if (!rest && !prefixcmp(options->long_name, arg + 3))
goto is_abbreviated;
if (!rest)
continue;
}
if (*rest) {
if (*rest != '=')
continue;
p->opt = rest + 1;
}
return get_value(p, options, flags);
}
if (abbrev_option)
return get_value(p, abbrev_option, abbrev_flags);
return error("unknown option `%s'", arg);
}
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;
for (; args.argc; args.argc--, args.argv++) {
const char *arg = args.argv[0];
if (*arg != '-' || !arg[1]) {
argv[j++] = args.argv[0];
continue;
}
if (arg[1] != '-') {
args.opt = arg + 1;
do {
if (*args.opt == 'h')
usage_with_options(usagestr, options);
if (parse_short_opt(&args, options) < 0)
usage_with_options(usagestr, options);
} while (args.opt);
continue;
}
if (!arg[2]) { /* "--" */
if (!(flags & PARSE_OPT_KEEP_DASHDASH)) {
args.argc--;
args.argv++;
}
break;
}
if (!strcmp(arg + 2, "help"))
usage_with_options(usagestr, options);
if (parse_long_opt(&args, arg + 2, options))
usage_with_options(usagestr, options);
}
memmove(argv + j, args.argv, args.argc * sizeof(*argv));
argv[j + args.argc] = NULL;
return j + args.argc;
}
#define USAGE_OPTS_WIDTH 24
#define USAGE_GAP 2
void usage_with_options(const char * const *usagestr,
const struct option *opts)
{
fprintf(stderr, "usage: %s\n", *usagestr++);
while (*usagestr && **usagestr)
fprintf(stderr, " or: %s\n", *usagestr++);
while (*usagestr)
fprintf(stderr, " %s\n", *usagestr++);
if (opts->type != OPTION_GROUP)
fputc('\n', stderr);
for (; opts->type != OPTION_END; opts++) {
size_t pos;
int pad;
if (opts->type == OPTION_GROUP) {
fputc('\n', stderr);
if (*opts->help)
fprintf(stderr, "%s\n", opts->help);
continue;
}
pos = fprintf(stderr, " ");
if (opts->short_name)
pos += fprintf(stderr, "-%c", opts->short_name);
if (opts->long_name && opts->short_name)
pos += fprintf(stderr, ", ");
if (opts->long_name)
pos += fprintf(stderr, "--%s", opts->long_name);
switch (opts->type) {
case OPTION_INTEGER:
if (opts->flags & PARSE_OPT_OPTARG)
pos += fprintf(stderr, " [<n>]");
else
pos += fprintf(stderr, " <n>");
break;
case OPTION_CALLBACK:
if (opts->flags & PARSE_OPT_NOARG)
break;
/* FALLTHROUGH */
case OPTION_STRING:
if (opts->argh) {
if (opts->flags & PARSE_OPT_OPTARG)
pos += fprintf(stderr, " [<%s>]", opts->argh);
else
pos += fprintf(stderr, " <%s>", opts->argh);
} else {
if (opts->flags & PARSE_OPT_OPTARG)
pos += fprintf(stderr, " [...]");
else
pos += fprintf(stderr, " ...");
}
break;
default:
break;
}
if (pos <= USAGE_OPTS_WIDTH)
pad = USAGE_OPTS_WIDTH - pos;
else {
fputc('\n', stderr);
pad = USAGE_OPTS_WIDTH;
}
fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
}
fputc('\n', stderr);
exit(129);
}
/*----- some often used options -----*/
#include "cache.h"
int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
{
int v;
if (!arg) {
v = unset ? 0 : DEFAULT_ABBREV;
} else {
v = strtol(arg, (char **)&arg, 10);
if (*arg)
return opterror(opt, "expects a numerical value", 0);
if (v && v < MINIMUM_ABBREV)
v = MINIMUM_ABBREV;
else if (v > 40)
v = 40;
}
*(int *)(opt->value) = v;
return 0;
}

70
parse-options.h Normal file
View File

@@ -0,0 +1,70 @@
#ifndef PARSE_OPTIONS_H
#define PARSE_OPTIONS_H
enum parse_opt_type {
OPTION_END,
OPTION_GROUP,
OPTION_BOOLEAN,
OPTION_STRING,
OPTION_INTEGER,
OPTION_CALLBACK,
};
enum parse_opt_flags {
PARSE_OPT_KEEP_DASHDASH = 1,
};
enum parse_opt_option_flags {
PARSE_OPT_OPTARG = 1,
PARSE_OPT_NOARG = 2,
};
struct option;
typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
struct option {
enum parse_opt_type type;
int short_name;
const char *long_name;
void *value;
const char *argh;
const char *help;
int flags;
parse_opt_cb *callback;
/* holds default value for PARSE_OPT_OPTARG,
though callbacks can use it like they want */
intptr_t defval;
};
#define OPT_END() { OPTION_END }
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) }
#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) }
#define OPT_CALLBACK(s, l, v, a, h, f) \
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
/* parse_options() will filter out the processed options and leave the
* non-option argments in argv[].
* Returns the number of arguments left in argv[].
*/
extern int parse_options(int argc, const char **argv,
const struct option *options,
const char * const usagestr[], int flags);
extern NORETURN void usage_with_options(const char * const *usagestr,
const struct option *options);
/*----- some often used options -----*/
extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose")
#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet")
#define OPT__DRY_RUN(var) OPT_BOOLEAN('n', "dry-run", (var), "dry run")
#define OPT__ABBREV(var) \
{ OPTION_CALLBACK, 0, "abbrev", (var), "n", \
"use <n> digits to display SHA-1s", \
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
#endif

View File

@@ -1,6 +1,40 @@
/*
* Simple text-based progress display module for GIT
*
* Copyright (c) 2007 by Nicolas Pitre <nico@cam.org>
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "git-compat-util.h"
#include "progress.h"
#define TP_IDX_MAX 8
struct throughput {
struct timeval prev_tv;
off_t total;
unsigned long count;
unsigned long avg_bytes;
unsigned long last_bytes[TP_IDX_MAX];
unsigned int avg_misecs;
unsigned int last_misecs[TP_IDX_MAX];
unsigned int idx;
char display[32];
};
struct progress {
const char *title;
int last_value;
unsigned total;
unsigned last_percent;
unsigned delay;
unsigned delayed_percent_treshold;
struct throughput *throughput;
};
static volatile sig_atomic_t progress_update;
#ifndef __MINGW32__
@@ -78,10 +112,11 @@ static void clear_progress_signal(void)
progress_update = 0;
}
int display_progress(struct progress *progress, unsigned n)
static int display(struct progress *progress, unsigned n, int done)
{
char *eol, *tp;
if (progress->delay) {
char buf[80];
if (!progress_update || --progress->delay)
return 0;
if (progress->total) {
@@ -94,60 +129,151 @@ int display_progress(struct progress *progress, unsigned n)
return 0;
}
}
if (snprintf(buf, sizeof(buf),
progress->delayed_title, progress->total))
fprintf(stderr, "%s\n", buf);
}
progress->last_value = n;
tp = (progress->throughput) ? progress->throughput->display : "";
eol = done ? ", done. \n" : " \r";
if (progress->total) {
unsigned percent = n * 100 / progress->total;
if (percent != progress->last_percent || progress_update) {
progress->last_percent = percent;
fprintf(stderr, "%s%4u%% (%u/%u) done\r",
progress->prefix, percent, n, progress->total);
fprintf(stderr, "%s: %3u%% (%u/%u)%s%s",
progress->title, percent, n,
progress->total, tp, eol);
progress_update = 0;
progress->need_lf = 1;
return 1;
}
} else if (progress_update) {
fprintf(stderr, "%s%u\r", progress->prefix, n);
fprintf(stderr, "%s: %u%s%s", progress->title, n, tp, eol);
progress_update = 0;
progress->need_lf = 1;
return 1;
}
return 0;
}
void start_progress(struct progress *progress, const char *title,
const char *prefix, unsigned total)
void display_throughput(struct progress *progress, unsigned long n)
{
char buf[80];
progress->prefix = prefix;
progress->total = total;
progress->last_percent = -1;
progress->delay = 0;
progress->need_lf = 0;
if (snprintf(buf, sizeof(buf), title, total))
fprintf(stderr, "%s\n", buf);
set_progress_signal();
struct throughput *tp;
struct timeval tv;
unsigned int misecs;
if (!progress)
return;
tp = progress->throughput;
gettimeofday(&tv, NULL);
if (!tp) {
progress->throughput = tp = calloc(1, sizeof(*tp));
if (tp)
tp->prev_tv = tv;
return;
}
tp->total += n;
tp->count += n;
/*
* We have x = bytes and y = microsecs. We want z = KiB/s:
*
* z = (x / 1024) / (y / 1000000)
* z = x / y * 1000000 / 1024
* z = x / (y * 1024 / 1000000)
* z = x / y'
*
* To simplify things we'll keep track of misecs, or 1024th of a sec
* obtained with:
*
* y' = y * 1024 / 1000000
* y' = y / (1000000 / 1024)
* y' = y / 977
*/
misecs = (tv.tv_sec - tp->prev_tv.tv_sec) * 1024;
misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977;
if (misecs > 512) {
int l = sizeof(tp->display);
tp->prev_tv = tv;
tp->avg_bytes += tp->count;
tp->avg_misecs += misecs;
if (tp->total > 1 << 30) {
l -= snprintf(tp->display, l, ", %u.%2.2u GiB",
(int)(tp->total >> 30),
(int)(tp->total & ((1 << 30) - 1)) / 10737419);
} else if (tp->total > 1 << 20) {
l -= snprintf(tp->display, l, ", %u.%2.2u MiB",
(int)(tp->total >> 20),
((int)(tp->total & ((1 << 20) - 1))
* 100) >> 20);
} else if (tp->total > 1 << 10) {
l -= snprintf(tp->display, l, ", %u.%2.2u KiB",
(int)(tp->total >> 10),
((int)(tp->total & ((1 << 10) - 1))
* 100) >> 10);
} else {
l -= snprintf(tp->display, l, ", %u bytes",
(int)tp->total);
}
snprintf(tp->display + sizeof(tp->display) - l, l,
" | %lu KiB/s", tp->avg_bytes / tp->avg_misecs);
tp->avg_bytes -= tp->last_bytes[tp->idx];
tp->avg_misecs -= tp->last_misecs[tp->idx];
tp->last_bytes[tp->idx] = tp->count;
tp->last_misecs[tp->idx] = misecs;
tp->idx = (tp->idx + 1) % TP_IDX_MAX;
tp->count = 0;
if (progress->last_value != -1 && progress_update)
display(progress, progress->last_value, 0);
}
}
void start_progress_delay(struct progress *progress, const char *title,
const char *prefix, unsigned total,
unsigned percent_treshold, unsigned delay)
int display_progress(struct progress *progress, unsigned n)
{
progress->prefix = prefix;
return progress ? display(progress, n, 0) : 0;
}
struct progress *start_progress_delay(const char *title, unsigned total,
unsigned percent_treshold, unsigned delay)
{
struct progress *progress = malloc(sizeof(*progress));
if (!progress) {
/* unlikely, but here's a good fallback */
fprintf(stderr, "%s...\n", title);
return NULL;
}
progress->title = title;
progress->total = total;
progress->last_value = -1;
progress->last_percent = -1;
progress->delayed_percent_treshold = percent_treshold;
progress->delayed_title = title;
progress->delay = delay;
progress->need_lf = 0;
progress->throughput = NULL;
set_progress_signal();
return progress;
}
void stop_progress(struct progress *progress)
struct progress *start_progress(const char *title, unsigned total)
{
clear_progress_signal();
if (progress->need_lf)
fputc('\n', stderr);
return start_progress_delay(title, total, 0, 0);
}
void stop_progress(struct progress **p_progress)
{
struct progress *progress = *p_progress;
if (!progress)
return;
*p_progress = NULL;
if (progress->last_value != -1) {
/* Force the last update */
progress_update = 1;
display(progress, progress->last_value, 1);
}
clear_progress_signal();
free(progress->throughput);
free(progress);
}

View File

@@ -1,22 +1,13 @@
#ifndef PROGRESS_H
#define PROGRESS_H
struct progress {
const char *prefix;
unsigned total;
unsigned last_percent;
unsigned delay;
unsigned delayed_percent_treshold;
const char *delayed_title;
int need_lf;
};
struct progress;
void display_throughput(struct progress *progress, unsigned long n);
int display_progress(struct progress *progress, unsigned n);
void start_progress(struct progress *progress, const char *title,
const char *prefix, unsigned total);
void start_progress_delay(struct progress *progress, const char *title,
const char *prefix, unsigned total,
unsigned percent_treshold, unsigned delay);
void stop_progress(struct progress *progress);
struct progress *start_progress(const char *title, unsigned total);
struct progress *start_progress_delay(const char *title, unsigned total,
unsigned percent_treshold, unsigned delay);
void stop_progress(struct progress **progress);
#endif

View File

@@ -297,9 +297,9 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
* commits at the remote end and likely
* we were not up to date to begin with.
*/
error("remote '%s' is not a strict "
"subset of local ref '%s'. "
"maybe you are not up-to-date and "
error("remote '%s' is not an ancestor of\n"
" local '%s'.\n"
" Maybe you are not up-to-date and "
"need to pull first?",
ref->name,
ref->peer_ref->name);

View File

@@ -17,7 +17,7 @@ int recv_sideband(const char *me, int in_stream, int out, int err)
strcpy(buf, "remote:");
while (1) {
int band, len;
len = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX);
len = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX);
if (len == 0)
break;
if (len < 1) {
@@ -35,7 +35,22 @@ int recv_sideband(const char *me, int in_stream, int out, int err)
return SIDEBAND_REMOTE_ERROR;
case 2:
buf[7] = ' ';
safe_write(err, buf, 8+len);
len += 8;
while (1) {
int brk = 8;
while (brk < len) {
brk++;
if (buf[brk-1] == '\n' ||
buf[brk-1] == '\r')
break;
}
safe_write(err, buf, brk);
if (brk < len) {
memmove(buf + 8, buf + brk, len - brk);
len = len - brk + 8;
} else
break;
}
continue;
case 1:
safe_write(out, buf+8, len);

93
t/t0040-parse-options.sh Executable file
View File

@@ -0,0 +1,93 @@
#!/bin/sh
#
# Copyright (c) 2007 Johannes Schindelin
#
test_description='our own option parser'
. ./test-lib.sh
cat > expect.err << EOF
usage: test-parse-options <options>
-b, --boolean get a boolean
-i, --integer <n> get a integer
-j <n> get a integer, too
string options
-s, --string <string>
get a string
--string2 <str> get another string
EOF
test_expect_success 'test help' '
! test-parse-options -h > output 2> output.err &&
test ! -s output &&
git diff expect.err output.err
'
cat > expect << EOF
boolean: 2
integer: 1729
string: 123
EOF
test_expect_success 'short options' '
test-parse-options -s123 -b -i 1729 -b > output 2> output.err &&
git diff expect output &&
test ! -s output.err
'
cat > expect << EOF
boolean: 2
integer: 1729
string: 321
EOF
test_expect_success 'long options' '
test-parse-options --boolean --integer 1729 --boolean --string2=321 \
> output 2> output.err &&
test ! -s output.err &&
git diff expect output
'
cat > expect << EOF
boolean: 1
integer: 13
string: 123
arg 00: a1
arg 01: b1
arg 02: --boolean
EOF
test_expect_success 'intermingled arguments' '
test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
> output 2> output.err &&
test ! -s output.err &&
git diff expect output
'
cat > expect << EOF
boolean: 0
integer: 2
string: (not set)
EOF
test_expect_success 'unambiguously abbreviated option' '
test-parse-options --int 2 --boolean --no-bo > output 2> output.err &&
test ! -s output.err &&
git diff expect output
'
test_expect_success 'unambiguously abbreviated option with "="' '
test-parse-options --int=2 > output 2> output.err &&
test ! -s output.err &&
git diff expect output
'
test_expect_failure 'ambiguously abbreviated option' '
test-parse-options --strin 123;
test $? != 129
'
test_done

View File

@@ -44,7 +44,7 @@ test_expect_success setup '
test_expect_success 'cherry-pick after renaming branch' '
git checkout rename2 &&
EDITOR=: VISUAL=: git cherry-pick added &&
git cherry-pick added &&
test -f opos &&
grep "Add extra line at the end" opos
@@ -53,7 +53,7 @@ test_expect_success 'cherry-pick after renaming branch' '
test_expect_success 'revert after renaming branch' '
git checkout rename1 &&
EDITOR=: VISUAL=: git revert added &&
git revert added &&
test -f spoo &&
! grep "Add extra line at the end" spoo

123
t/t3502-cherry-pick-merge.sh Executable file
View File

@@ -0,0 +1,123 @@
#!/bin/sh
test_description='cherry picking and reverting a merge
b---c
/ /
initial---a
'
. ./test-lib.sh
test_expect_success setup '
>A &&
>B &&
git add A B &&
git commit -m "Initial" &&
git tag initial &&
git branch side &&
echo new line >A &&
git commit -m "add line to A" A &&
git tag a &&
git checkout side &&
echo new line >B &&
git commit -m "add line to B" B &&
git tag b &&
git checkout master &&
git merge side &&
git tag c
'
test_expect_success 'cherry-pick a non-merge with -m should fail' '
git reset --hard &&
git checkout a^0 &&
! git cherry-pick -m 1 b &&
git diff --exit-code a
'
test_expect_success 'cherry pick a merge without -m should fail' '
git reset --hard &&
git checkout a^0 &&
! git cherry-pick c &&
git diff --exit-code a
'
test_expect_success 'cherry pick a merge (1)' '
git reset --hard &&
git checkout a^0 &&
git cherry-pick -m 1 c &&
git diff --exit-code c
'
test_expect_success 'cherry pick a merge (2)' '
git reset --hard &&
git checkout b^0 &&
git cherry-pick -m 2 c &&
git diff --exit-code c
'
test_expect_success 'cherry pick a merge relative to nonexistent parent should fail' '
git reset --hard &&
git checkout b^0 &&
! git cherry-pick -m 3 c
'
test_expect_success 'revert a non-merge with -m should fail' '
git reset --hard &&
git checkout c^0 &&
! git revert -m 1 b &&
git diff --exit-code c
'
test_expect_success 'revert a merge without -m should fail' '
git reset --hard &&
git checkout c^0 &&
! git revert c &&
git diff --exit-code c
'
test_expect_success 'revert a merge (1)' '
git reset --hard &&
git checkout c^0 &&
git revert -m 1 c &&
git diff --exit-code a
'
test_expect_success 'revert a merge (2)' '
git reset --hard &&
git checkout c^0 &&
git revert -m 2 c &&
git diff --exit-code b
'
test_expect_success 'revert a merge relative to nonexistent parent should fail' '
git reset --hard &&
git checkout c^0 &&
! git revert -m 3 c &&
git diff --exit-code c
'
test_done

View File

@@ -154,7 +154,7 @@ test_expect_success 'cherry-pick(U/U)' '
git reset --hard master &&
git cherry-pick side^ &&
git cherry-pick side &&
EDITOR=: VISUAL=: git revert HEAD &&
git revert HEAD &&
check_encoding 3
'
@@ -169,7 +169,7 @@ test_expect_success 'cherry-pick(L/L)' '
git reset --hard master &&
git cherry-pick side^ &&
git cherry-pick side &&
EDITOR=: VISUAL=: git revert HEAD &&
git revert HEAD &&
check_encoding 3 8859
'
@@ -184,7 +184,7 @@ test_expect_success 'cherry-pick(U/L)' '
git reset --hard master &&
git cherry-pick side^ &&
git cherry-pick side &&
EDITOR=: VISUAL=: git revert HEAD &&
git revert HEAD &&
check_encoding 3
'
@@ -200,7 +200,7 @@ test_expect_success 'cherry-pick(L/U)' '
git reset --hard master &&
git cherry-pick side^ &&
git cherry-pick side &&
EDITOR=: VISUAL=: git revert HEAD &&
git revert HEAD &&
check_encoding 3 8859
'

View File

@@ -0,0 +1,42 @@
#!/bin/sh
test_description='format-patch -s should force MIME encoding as needed'
. ./test-lib.sh
test_expect_success setup '
>F &&
git add F &&
git commit -m initial &&
echo new line >F &&
test_tick &&
git commit -m "This adds some lines to F" F
'
test_expect_success 'format normally' '
git format-patch --stdout -1 >output &&
! grep Content-Type output
'
test_expect_success 'format with signoff without funny signer name' '
git format-patch -s --stdout -1 >output &&
! grep Content-Type output
'
test_expect_success 'format with non ASCII signer name' '
GIT_COMMITTER_NAME="$B$O$^$N(B $B$U$K$*$&(B" \
git format-patch -s --stdout -1 >output &&
grep Content-Type output
'
test_done

View File

@@ -1,3 +1,6 @@
From nobody Mon Sep 17 00:00:00 2001
From: A U Thor <a.u.thor@example.com>
Date: Fri, 9 Jun 2006 00:44:16 -0700

0
t/t6300-for-each-ref.sh Normal file → Executable file
View File

View File

@@ -402,4 +402,11 @@ test_expect_success 'test resetting the index at give paths' '
'
test_expect_success 'resetting an unmodified path is a no-op' '
git reset --hard &&
git reset -- file1 &&
git diff-files --exit-code &&
git diff-index --cached --exit-code HEAD
'
test_done

View File

@@ -31,7 +31,6 @@ our \$projects_list = "";
our \$export_ok = "";
our \$strict_export = "";
CGI::Carp::set_programname("gitweb/gitweb.cgi");
EOF
cat >.git/description <<EOF
@@ -558,4 +557,27 @@ test_expect_success \
'gitweb_run "p=.git;a=tree;opt=--no-merges"'
test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
# gitweb config and repo config
cat >>gitweb_config.perl <<EOF
\$feature{'blame'}{'override'} = 1;
\$feature{'snapshot'}{'override'} = 1;
EOF
test_expect_success \
'config override: tree view, features disabled in repo config' \
'git config gitweb.blame no &&
git config gitweb.snapshot none &&
gitweb_run "p=.git;a=tree"'
test_debug 'cat gitweb.log'
test_expect_success \
'config override: tree view, features enabled in repo config' \
'git config gitweb.blame yes &&
git config gitweb.snapshot "zip,tgz, tbz2" &&
gitweb_run "p=.git;a=tree"'
test_debug 'cat gitweb.log'
test_done

35
test-parse-options.c Normal file
View File

@@ -0,0 +1,35 @@
#include "cache.h"
#include "parse-options.h"
static int boolean = 0;
static int integer = 0;
static char *string = NULL;
int main(int argc, const char **argv)
{
const char *usage[] = {
"test-parse-options <options>",
NULL
};
struct option options[] = {
OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"),
OPT_INTEGER('i', "integer", &integer, "get a integer"),
OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
OPT_GROUP("string options"),
OPT_STRING('s', "string", &string, "string", "get a string"),
OPT_STRING(0, "string2", &string, "str", "get another string"),
OPT_END(),
};
int i;
argc = parse_options(argc, argv, options, usage, 0);
printf("boolean: %d\n", boolean);
printf("integer: %d\n", integer);
printf("string: %s\n", string ? string : "(not set)");
for (i = 0; i < argc; i++)
printf("arg %02d: %s\n", i, argv[i]);
return 0;
}

View File

@@ -107,7 +107,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
return;
for (;;) {
int cmp, len;
int cmp = cmp, len;
if (!fgets(buffer, sizeof(buffer), f)) {
fclose(f);

View File

@@ -297,7 +297,7 @@ static void check_updates(struct cache_entry **src, int nr,
{
unsigned short mask = htons(CE_UPDATE);
unsigned cnt = 0, total = 0;
struct progress progress;
struct progress *progress = NULL;
char last_symlink[PATH_MAX];
if (o->update && o->verbose_update) {
@@ -307,8 +307,8 @@ static void check_updates(struct cache_entry **src, int nr,
total++;
}
start_progress_delay(&progress, "Checking %u files out...",
"", total, 50, 2);
progress = start_progress_delay("Checking out files",
total, 50, 2);
cnt = 0;
}
@@ -316,9 +316,8 @@ static void check_updates(struct cache_entry **src, int nr,
while (nr--) {
struct cache_entry *ce = *src++;
if (total)
if (!ce->ce_mode || ce->ce_flags & mask)
display_progress(&progress, ++cnt);
if (!ce->ce_mode || ce->ce_flags & mask)
display_progress(progress, ++cnt);
if (!ce->ce_mode) {
if (o->update)
unlink_entry(ce->name, last_symlink);
@@ -332,8 +331,7 @@ static void check_updates(struct cache_entry **src, int nr,
}
}
}
if (total)
stop_progress(&progress);;
stop_progress(&progress);
}
int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o)