提交 91efcf60 编写于 作者: J Junio C Hamano

Merge branch 'master' into jc/fmt-patch

* master:
  Split up builtin commands into separate files from git.c
  git-log produces no output
  fix pack-object buffer size
  mailinfo: decode underscore used in "Q" encoding properly.
  Reintroduce svn pools to solve the memory leak.
  pack-objects: do not stop at object that is "too small"
  git-commit --amend: two fixes.
  get_tree_entry(): make it available from tree-walk
  sha1_name.c: no need to include diff.h; tree-walk.h will do.
  sha1_name.c: prepare to make get_tree_entry() reusable from others.
  get_sha1() shorthands for blob/tree objects
  pre-commit hook: complain about conflict markers.
  git-merge: a bit more readable user guidance.
  diff: move diff.c to diff-lib.c to make room.
  git log: don't do merge diffs by default
  Allow "git repack" users to specify repacking window/depth
  Document git-clone --reference
  Fix filename scaling for binary files
  Fix uninteresting tags in new revision parsing

Conflicts:

    Adjusted the addition of fmt-patch to match the recent split
    from git.c to builtin.log.c.
......@@ -10,6 +10,7 @@ SYNOPSIS
--------
[verse]
'git-clone' [-l [-s]] [-q] [-n] [--bare] [-o <name>] [-u <upload-pack>]
[--reference <repository>]
<repository> [<directory>]
DESCRIPTION
......@@ -46,10 +47,18 @@ OPTIONS
-s::
When the repository to clone is on the local machine,
instead of using hard links, automatically setup
.git/objects/info/alternatives to share the objects
.git/objects/info/alternates to share the objects
with the source repository. The resulting repository
starts out without any object of its own.
--reference <repository>::
If the reference repository is on the local machine
automatically setup .git/objects/info/alternates to
obtain objects from the reference repository. Using
an already existing repository as an alternate will
require less objects to be copied from the repository
being cloned, reducing network and local storage costs.
--quiet::
-q::
Operate quietly. This flag is passed to "rsync" and
......@@ -112,6 +121,16 @@ $ git show-branch
------------
Clone from upstream while borrowing from an existing local directory::
+
------------
$ git clone --reference my2.6 \
git://git.kernel.org/pub/scm/.../linux-2.7 \
my2.7
$ cd my2.7
------------
Create a bare repository to publish your changes to the public::
+
------------
......
......@@ -199,7 +199,7 @@ LIB_H = \
tree-walk.h log-tree.h
DIFF_OBJS = \
diff.o diffcore-break.o diffcore-order.o \
diff-lib.o diffcore-break.o diffcore-order.o \
diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o \
diffcore-delta.o log-tree.o
......@@ -213,6 +213,9 @@ LIB_OBJS = \
fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
$(DIFF_OBJS)
BUILTIN_OBJS = \
builtin-log.o builtin-help.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz
......@@ -462,10 +465,10 @@ all:
strip: $(PROGRAMS) git$X
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
git$X: git.c common-cmds.h $(GITLIBS)
git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS)
$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
$(ALL_LDFLAGS) $(LIBS)
$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
$(BUILT_INS): git$X
rm -f $@ && ln git$X $@
......@@ -565,7 +568,7 @@ init-db.o: init-db.c
$(CC) -c $(ALL_CFLAGS) \
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c
$(LIB_OBJS): $(LIB_H)
$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(GITLIBS)
$(DIFF_OBJS): diffcore.h
......
/*
* builtin-help.c
*
* Builtin help-related commands (help, usage, version)
*/
#include "cache.h"
#include "builtin.h"
#include "exec_cmd.h"
#include "common-cmds.h"
static const char git_usage[] =
"Usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ ARGS ]";
/* most gui terms set COLUMNS (although some don't export it) */
static int term_columns(void)
{
char *col_string = getenv("COLUMNS");
int n_cols = 0;
if (col_string && (n_cols = atoi(col_string)) > 0)
return n_cols;
#ifdef TIOCGWINSZ
{
struct winsize ws;
if (!ioctl(1, TIOCGWINSZ, &ws)) {
if (ws.ws_col)
return ws.ws_col;
}
}
#endif
return 80;
}
static void oom(void)
{
fprintf(stderr, "git: out of memory\n");
exit(1);
}
static inline void mput_char(char c, unsigned int num)
{
while(num--)
putchar(c);
}
static struct cmdname {
size_t len;
char name[1];
} **cmdname;
static int cmdname_alloc, cmdname_cnt;
static void add_cmdname(const char *name, int len)
{
struct cmdname *ent;
if (cmdname_alloc <= cmdname_cnt) {
cmdname_alloc = cmdname_alloc + 200;
cmdname = realloc(cmdname, cmdname_alloc * sizeof(*cmdname));
if (!cmdname)
oom();
}
ent = malloc(sizeof(*ent) + len);
if (!ent)
oom();
ent->len = len;
memcpy(ent->name, name, len);
ent->name[len] = 0;
cmdname[cmdname_cnt++] = ent;
}
static int cmdname_compare(const void *a_, const void *b_)
{
struct cmdname *a = *(struct cmdname **)a_;
struct cmdname *b = *(struct cmdname **)b_;
return strcmp(a->name, b->name);
}
static void pretty_print_string_list(struct cmdname **cmdname, int longest)
{
int cols = 1, rows;
int space = longest + 1; /* min 1 SP between words */
int max_cols = term_columns() - 1; /* don't print *on* the edge */
int i, j;
if (space < max_cols)
cols = max_cols / space;
rows = (cmdname_cnt + cols - 1) / cols;
qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
for (i = 0; i < rows; i++) {
printf(" ");
for (j = 0; j < cols; j++) {
int n = j * rows + i;
int size = space;
if (n >= cmdname_cnt)
break;
if (j == cols-1 || n + rows >= cmdname_cnt)
size = 1;
printf("%-*s", size, cmdname[n]->name);
}
putchar('\n');
}
}
static void list_commands(const char *exec_path, const char *pattern)
{
unsigned int longest = 0;
char path[PATH_MAX];
int dirlen;
DIR *dir = opendir(exec_path);
struct dirent *de;
if (!dir) {
fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno));
exit(1);
}
dirlen = strlen(exec_path);
if (PATH_MAX - 20 < dirlen) {
fprintf(stderr, "git: insanely long exec-path '%s'\n",
exec_path);
exit(1);
}
memcpy(path, exec_path, dirlen);
path[dirlen++] = '/';
while ((de = readdir(dir)) != NULL) {
struct stat st;
int entlen;
if (strncmp(de->d_name, "git-", 4))
continue;
strcpy(path+dirlen, de->d_name);
if (stat(path, &st) || /* stat, not lstat */
!S_ISREG(st.st_mode) ||
!(st.st_mode & S_IXUSR))
continue;
entlen = strlen(de->d_name);
if (4 < entlen && !strcmp(de->d_name + entlen - 4, ".exe"))
entlen -= 4;
if (longest < entlen)
longest = entlen;
add_cmdname(de->d_name + 4, entlen-4);
}
closedir(dir);
printf("git commands available in '%s'\n", exec_path);
printf("----------------------------");
mput_char('-', strlen(exec_path));
putchar('\n');
pretty_print_string_list(cmdname, longest - 4);
putchar('\n');
}
static void list_common_cmds_help(void)
{
int i, longest = 0;
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
if (longest < strlen(common_cmds[i].name))
longest = strlen(common_cmds[i].name);
}
puts("The most commonly used git commands are:");
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
printf(" %s", common_cmds[i].name);
mput_char(' ', longest - strlen(common_cmds[i].name) + 4);
puts(common_cmds[i].help);
}
puts("(use 'git help -a' to get a list of all installed git commands)");
}
void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
{
if (fmt) {
va_list ap;
va_start(ap, fmt);
printf("git: ");
vprintf(fmt, ap);
va_end(ap);
putchar('\n');
}
else
puts(git_usage);
if (exec_path) {
putchar('\n');
if (show_all)
list_commands(exec_path, "git-*");
else
list_common_cmds_help();
}
exit(1);
}
static void show_man_page(const char *git_cmd)
{
const char *page;
if (!strncmp(git_cmd, "git", 3))
page = git_cmd;
else {
int page_len = strlen(git_cmd) + 4;
char *p = malloc(page_len + 1);
strcpy(p, "git-");
strcpy(p + 4, git_cmd);
p[page_len] = 0;
page = p;
}
execlp("man", "man", page, NULL);
}
int cmd_version(int argc, const char **argv, char **envp)
{
printf("git version %s\n", git_version_string);
return 0;
}
int cmd_help(int argc, const char **argv, char **envp)
{
const char *help_cmd = argv[1];
if (!help_cmd)
cmd_usage(0, git_exec_path(), NULL);
else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a"))
cmd_usage(1, git_exec_path(), NULL);
else
show_man_page(help_cmd);
return 0;
}
/*
* Builtin "git log" and related commands (show, whatchanged)
*
* (C) Copyright 2006 Linus Torvalds
* 2006 Junio Hamano
*/
#include "cache.h"
#include "commit.h"
#include "diff.h"
#include "revision.h"
#include "log-tree.h"
#include "builtin.h"
static int cmd_log_wc(int argc, const char **argv, char **envp,
struct rev_info *rev)
{
struct commit *commit;
rev->abbrev = DEFAULT_ABBREV;
rev->commit_format = CMIT_FMT_DEFAULT;
rev->verbose_header = 1;
argc = setup_revisions(argc, argv, rev, "HEAD");
if (argc > 1)
die("unrecognized argument: %s", argv[1]);
prepare_revision_walk(rev);
setup_pager();
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
return 0;
}
int cmd_whatchanged(int argc, const char **argv, char **envp)
{
struct rev_info rev;
init_revisions(&rev);
rev.diff = 1;
rev.diffopt.recursive = 1;
return cmd_log_wc(argc, argv, envp, &rev);
}
int cmd_show(int argc, const char **argv, char **envp)
{
struct rev_info rev;
init_revisions(&rev);
rev.diff = 1;
rev.diffopt.recursive = 1;
rev.combine_merges = 1;
rev.dense_combined_merges = 1;
rev.always_show_header = 1;
rev.ignore_merges = 0;
rev.no_walk = 1;
return cmd_log_wc(argc, argv, envp, &rev);
}
int cmd_log(int argc, const char **argv, char **envp)
{
struct rev_info rev;
init_revisions(&rev);
rev.always_show_header = 1;
rev.diffopt.recursive = 1;
return cmd_log_wc(argc, argv, envp, &rev);
}
int cmd_format_patch(int argc, const char **argv, char **envp)
{
struct commit *commit;
struct commit **list = NULL;
struct rev_info rev;
int nr = 0;
init_revisions(&rev);
rev.commit_format = CMIT_FMT_EMAIL;
rev.verbose_header = 1;
rev.diff = 1;
rev.diffopt.with_raw = 0;
rev.diffopt.with_stat = 1;
rev.combine_merges = 0;
rev.ignore_merges = 1;
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
argc = setup_revisions(argc, argv, &rev, "HEAD");
prepare_revision_walk(&rev);
while ((commit = get_revision(&rev)) != NULL) {
nr++;
list = realloc(list, nr * sizeof(list[0]));
list[nr - 1] = commit;
}
while (0 <= --nr) {
int shown;
commit = list[nr];
shown = log_tree_commit(&rev, commit);
free(commit->buffer);
commit->buffer = NULL;
if (shown)
printf("-- \n%s\n\n", git_version_string);
}
free(list);
return 0;
}
#ifndef BUILTIN_H
#define BUILTIN_H
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
extern const char git_version_string[];
void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
#ifdef __GNUC__
__attribute__((__format__(__printf__, 3, 4), __noreturn__))
#endif
;
extern int cmd_help(int argc, const char **argv, char **envp);
extern int cmd_version(int argc, const char **argv, char **envp);
extern int cmd_whatchanged(int argc, const char **argv, char **envp);
extern int cmd_show(int argc, const char **argv, char **envp);
extern int cmd_log(int argc, const char **argv, char **envp);
extern int cmd_format_patch(int argc, const char **argv, char **envp);
#endif
......@@ -250,13 +250,14 @@ static void show_stats(struct diffstat_t* data)
for (i = 0; i < data->nr; i++) {
struct diffstat_file *file = data->files[i];
len = strlen(file->name);
if (max_len < len)
max_len = len;
if (file->is_binary || file->is_unmerged)
continue;
if (max_change < file->added + file->deleted)
max_change = file->added + file->deleted;
len = strlen(file->name);
if (max_len < len)
max_len = len;
}
for (i = 0; i < data->nr; i++) {
......
......@@ -167,8 +167,13 @@ run_status () {
fi
case "$committable" in
0)
echo "nothing to commit"
exit 1
case "$amend" in
t)
echo "# No changes" ;;
*)
echo "nothing to commit" ;;
esac
exit 1 ;;
esac
exit 0
)
......@@ -365,14 +370,16 @@ tt*)
die "Only one of -c/-C/-F/-m can be used." ;;
esac
case "$#,$also$only" in
*,tt)
case "$#,$also,$only,$amend" in
*,t,t,*)
die "Only one of --include/--only can be used." ;;
0,t)
0,t,,* | 0,,t,)
die "No paths with --include/--only does not make sense." ;;
0,)
0,,t,t)
only_include_assumed="# Clever... amending the last one with dirty index." ;;
0,,,*)
;;
*,)
*,,,*)
only_include_assumed="# Explicit paths specified without -i nor -o; assuming --only paths..."
also=
;;
......
......@@ -335,5 +335,5 @@ Conflicts:
then
git-rerere
fi
die "Automatic merge failed; fix up by hand"
die "Automatic merge failed; fix conflicts and then commit the result."
fi
......@@ -5,9 +5,9 @@
USAGE='[-a] [-d] [-f] [-l] [-n] [-q]'
. git-sh-setup
no_update_info= all_into_one= remove_redundant=
local= quiet= no_reuse_delta=
local= quiet= no_reuse_delta= extra=
while case "$#" in 0) break ;; esac
do
case "$1" in
......@@ -17,6 +17,8 @@ do
-q) quiet=-q ;;
-f) no_reuse_delta=--no-reuse-delta ;;
-l) local=--local ;;
--window=*) extra="$extra $1" ;;
--depth=*) extra="$extra $1" ;;
*) usage ;;
esac
shift
......@@ -40,7 +42,7 @@ case ",$all_into_one," in
find . -type f \( -name '*.pack' -o -name '*.idx' \) -print`
;;
esac
pack_objects="$pack_objects $local $quiet $no_reuse_delta"
pack_objects="$pack_objects $local $quiet $no_reuse_delta$extra"
name=$(git-rev-list --objects --all $rev_list 2>&1 |
git-pack-objects --non-empty $pack_objects .tmp-pack) ||
exit 1
......
......@@ -136,8 +136,10 @@ sub file {
print "... $rev $path ...\n" if $opt_v;
my (undef, $properties);
my $pool = SVN::Pool->new();
eval { (undef, $properties)
= $self->{'svn'}->get_file($path,$rev,$fh); };
= $self->{'svn'}->get_file($path,$rev,$fh,$pool); };
$pool->clear;
if($@) {
return undef if $@ =~ /Attempted to get checksum/;
die $@;
......
......@@ -11,215 +11,8 @@
#include <sys/ioctl.h>
#include "git-compat-util.h"
#include "exec_cmd.h"
#include "common-cmds.h"
#include "cache.h"
#include "commit.h"
#include "diff.h"
#include "revision.h"
#include "log-tree.h"
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
static const char git_usage[] =
"Usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ ARGS ]";
/* most gui terms set COLUMNS (although some don't export it) */
static int term_columns(void)
{
char *col_string = getenv("COLUMNS");
int n_cols = 0;
if (col_string && (n_cols = atoi(col_string)) > 0)
return n_cols;
#ifdef TIOCGWINSZ
{
struct winsize ws;
if (!ioctl(1, TIOCGWINSZ, &ws)) {
if (ws.ws_col)
return ws.ws_col;
}
}
#endif
return 80;
}
static void oom(void)
{
fprintf(stderr, "git: out of memory\n");
exit(1);
}
static inline void mput_char(char c, unsigned int num)
{
while(num--)
putchar(c);
}
static struct cmdname {
size_t len;
char name[1];
} **cmdname;
static int cmdname_alloc, cmdname_cnt;
static void add_cmdname(const char *name, int len)
{
struct cmdname *ent;
if (cmdname_alloc <= cmdname_cnt) {
cmdname_alloc = cmdname_alloc + 200;
cmdname = realloc(cmdname, cmdname_alloc * sizeof(*cmdname));
if (!cmdname)
oom();
}
ent = malloc(sizeof(*ent) + len);
if (!ent)
oom();
ent->len = len;
memcpy(ent->name, name, len);
ent->name[len] = 0;
cmdname[cmdname_cnt++] = ent;
}
static int cmdname_compare(const void *a_, const void *b_)
{
struct cmdname *a = *(struct cmdname **)a_;
struct cmdname *b = *(struct cmdname **)b_;
return strcmp(a->name, b->name);
}
static void pretty_print_string_list(struct cmdname **cmdname, int longest)
{
int cols = 1, rows;
int space = longest + 1; /* min 1 SP between words */
int max_cols = term_columns() - 1; /* don't print *on* the edge */
int i, j;
if (space < max_cols)
cols = max_cols / space;
rows = (cmdname_cnt + cols - 1) / cols;
qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
for (i = 0; i < rows; i++) {
printf(" ");
for (j = 0; j < cols; j++) {
int n = j * rows + i;
int size = space;
if (n >= cmdname_cnt)
break;
if (j == cols-1 || n + rows >= cmdname_cnt)
size = 1;
printf("%-*s", size, cmdname[n]->name);
}
putchar('\n');
}
}
static void list_commands(const char *exec_path, const char *pattern)
{
unsigned int longest = 0;
char path[PATH_MAX];
int dirlen;
DIR *dir = opendir(exec_path);
struct dirent *de;
if (!dir) {
fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno));
exit(1);
}
dirlen = strlen(exec_path);
if (PATH_MAX - 20 < dirlen) {
fprintf(stderr, "git: insanely long exec-path '%s'\n",
exec_path);
exit(1);
}
memcpy(path, exec_path, dirlen);
path[dirlen++] = '/';
while ((de = readdir(dir)) != NULL) {
struct stat st;
int entlen;
if (strncmp(de->d_name, "git-", 4))
continue;
strcpy(path+dirlen, de->d_name);
if (stat(path, &st) || /* stat, not lstat */
!S_ISREG(st.st_mode) ||
!(st.st_mode & S_IXUSR))
continue;
entlen = strlen(de->d_name);
if (4 < entlen && !strcmp(de->d_name + entlen - 4, ".exe"))
entlen -= 4;
if (longest < entlen)
longest = entlen;
add_cmdname(de->d_name + 4, entlen-4);
}
closedir(dir);
printf("git commands available in '%s'\n", exec_path);
printf("----------------------------");
mput_char('-', strlen(exec_path));
putchar('\n');
pretty_print_string_list(cmdname, longest - 4);
putchar('\n');
}
static void list_common_cmds_help(void)
{
int i, longest = 0;
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
if (longest < strlen(common_cmds[i].name))
longest = strlen(common_cmds[i].name);
}
puts("The most commonly used git commands are:");
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
printf(" %s", common_cmds[i].name);
mput_char(' ', longest - strlen(common_cmds[i].name) + 4);
puts(common_cmds[i].help);
}
puts("(use 'git help -a' to get a list of all installed git commands)");
}
#ifdef __GNUC__
static void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
__attribute__((__format__(__printf__, 3, 4), __noreturn__));
#endif
static void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
{
if (fmt) {
va_list ap;
va_start(ap, fmt);
printf("git: ");
vprintf(fmt, ap);
va_end(ap);
putchar('\n');
}
else
puts(git_usage);
if (exec_path) {
putchar('\n');
if (show_all)
list_commands(exec_path, "git-*");
else
list_common_cmds_help();
}
exit(1);
}
#include "builtin.h"
static void prepend_to_path(const char *dir, int len)
{
......@@ -240,138 +33,7 @@ static void prepend_to_path(const char *dir, int len)
setenv("PATH", path, 1);
}
static void show_man_page(const char *git_cmd)
{
const char *page;
if (!strncmp(git_cmd, "git", 3))
page = git_cmd;
else {
int page_len = strlen(git_cmd) + 4;
char *p = malloc(page_len + 1);
strcpy(p, "git-");
strcpy(p + 4, git_cmd);
p[page_len] = 0;
page = p;
}
execlp("man", "man", page, NULL);
}
static int cmd_version(int argc, const char **argv, char **envp)
{
printf("git version %s\n", GIT_VERSION);
return 0;
}
static int cmd_help(int argc, const char **argv, char **envp)
{
const char *help_cmd = argv[1];
if (!help_cmd)
cmd_usage(0, git_exec_path(), NULL);
else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a"))
cmd_usage(1, git_exec_path(), NULL);
else
show_man_page(help_cmd);
return 0;
}
static int cmd_format_patch(int argc, const char **argv, char **envp)
{
struct commit *commit;
struct commit **list = NULL;
struct rev_info rev;
int nr = 0;
init_revisions(&rev);
rev.commit_format = CMIT_FMT_EMAIL;
rev.verbose_header = 1;
rev.diff = 1;
rev.diffopt.with_raw = 0;
rev.diffopt.with_stat = 1;
rev.combine_merges = 0;
rev.ignore_merges = 1;
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
argc = setup_revisions(argc, argv, &rev, "HEAD");
prepare_revision_walk(&rev);
while ((commit = get_revision(&rev)) != NULL) {
nr++;
list = realloc(list, nr * sizeof(list[0]));
list[nr - 1] = commit;
}
while (0 <= --nr) {
int shown;
commit = list[nr];
shown = log_tree_commit(&rev, commit);
free(commit->buffer);
commit->buffer = NULL;
if (shown)
printf("-- \n%s\n\n", GIT_VERSION);
}
free(list);
return 0;
}
static int cmd_log_wc(int argc, const char **argv, char **envp,
struct rev_info *rev)
{
struct commit *commit;
rev->abbrev = DEFAULT_ABBREV;
rev->commit_format = CMIT_FMT_DEFAULT;
rev->verbose_header = 1;
argc = setup_revisions(argc, argv, rev, "HEAD");
if (argc > 1)
die("unrecognized argument: %s", argv[1]);
prepare_revision_walk(rev);
setup_pager();
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
return 0;
}
static int cmd_wc(int argc, const char **argv, char **envp)
{
struct rev_info rev;
init_revisions(&rev);
rev.diff = 1;
rev.diffopt.recursive = 1;
return cmd_log_wc(argc, argv, envp, &rev);
}
static int cmd_show(int argc, const char **argv, char **envp)
{
struct rev_info rev;
init_revisions(&rev);
rev.diff = 1;
rev.diffopt.recursive = 1;
rev.combine_merges = 1;
rev.dense_combined_merges = 1;
rev.always_show_header = 1;
rev.ignore_merges = 0;
rev.no_walk = 1;
return cmd_log_wc(argc, argv, envp, &rev);
}
static int cmd_log(int argc, const char **argv, char **envp)
{
struct rev_info rev;
init_revisions(&rev);
rev.always_show_header = 1;
rev.diffopt.recursive = 1;
rev.combine_merges = 1;
rev.ignore_merges = 0;
return cmd_log_wc(argc, argv, envp, &rev);
}
const char git_version_string[] = GIT_VERSION;
static void handle_internal_command(int argc, const char **argv, char **envp)
{
......@@ -383,7 +45,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "version", cmd_version },
{ "help", cmd_help },
{ "log", cmd_log },
{ "whatchanged", cmd_wc },
{ "whatchanged", cmd_whatchanged },
{ "show", cmd_show },
{ "fmt-patch", cmd_format_patch },
};
......
......@@ -405,7 +405,7 @@ static unsigned hexval(int c)
return ~0;
}
static int decode_q_segment(char *in, char *ot, char *ep)
static int decode_q_segment(char *in, char *ot, char *ep, int rfc2047)
{
int c;
while ((c = *in++) != 0 && (in <= ep)) {
......@@ -414,9 +414,11 @@ static int decode_q_segment(char *in, char *ot, char *ep)
if (d == '\n' || !d)
break; /* drop trailing newline */
*ot++ = ((hexval(d) << 4) | hexval(*in++));
continue;
}
else
*ot++ = c;
if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */
c = 0x20;
*ot++ = c;
}
*ot = 0;
return 0;
......@@ -547,7 +549,7 @@ static void decode_header_bq(char *it)
sz = decode_b_segment(cp + 3, piecebuf, ep);
break;
case 'q':
sz = decode_q_segment(cp + 3, piecebuf, ep);
sz = decode_q_segment(cp + 3, piecebuf, ep, 1);
break;
}
if (sz < 0)
......@@ -569,7 +571,7 @@ static void decode_transfer_encoding(char *line)
switch (transfer_encoding) {
case TE_QP:
ep = line + strlen(line);
decode_q_segment(line, line, ep);
decode_q_segment(line, line, ep, 0);
break;
case TE_BASE64:
ep = line + strlen(line);
......
......@@ -1052,7 +1052,7 @@ static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_de
if (cur_entry->delta)
max_size = cur_entry->delta_size-1;
if (sizediff >= max_size)
return -1;
return 0;
delta_buf = diff_delta(old->data, oldsize,
cur->data, size, &delta_size, max_size);
if (!delta_buf)
......@@ -1231,7 +1231,7 @@ static void setup_progress_signal(void)
int main(int argc, char **argv)
{
SHA_CTX ctx;
char line[PATH_MAX + 20];
char line[40 + 1 + PATH_MAX + 2];
int window = 10, depth = 10, pack_to_stdout = 0;
struct object_entry **list;
int num_preferred_base = 0;
......
......@@ -8,6 +8,7 @@
static void run_pager(const char *pager)
{
execlp(pager, pager, NULL);
execl("/bin/sh", "sh", "-c", pager, NULL);
}
void setup_pager(void)
......@@ -47,5 +48,6 @@ void setup_pager(void)
setenv("LESS", "-S", 0);
run_pager(pager);
die("unable to execute pager '%s'", pager);
exit(255);
}
......@@ -152,6 +152,7 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object
if (parse_commit(commit) < 0)
die("unable to parse commit %s", name);
if (flags & UNINTERESTING) {
commit->object.flags |= UNINTERESTING;
mark_parents_uninteresting(commit);
revs->limited = 1;
}
......
......@@ -3,6 +3,7 @@
#include "commit.h"
#include "tree.h"
#include "blob.h"
#include "tree-walk.h"
static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
{
......@@ -455,6 +456,19 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1)
*/
int get_sha1(const char *name, unsigned char *sha1)
{
int ret;
unsigned unused;
prepare_alt_odb();
return get_sha1_1(name, strlen(name), sha1);
ret = get_sha1_1(name, strlen(name), sha1);
if (ret < 0) {
const char *cp = strchr(name, ':');
if (cp) {
unsigned char tree_sha1[20];
if (!get_sha1_1(name, cp-name, tree_sha1))
return get_tree_entry(tree_sha1, cp+1, sha1,
&unused);
}
}
return ret;
}
......@@ -114,6 +114,8 @@ EOF
git commit -m 'Merged "mybranch" changes.' -i hello
test_done
cat > show-branch.expect << EOF
* [master] Merged "mybranch" changes.
! [mybranch] Some work.
......
......@@ -61,6 +61,9 @@ perl -e '
if (/^\s* /) {
bad_line("indent SP followed by a TAB", $_);
}
if (/^(?:[<>=]){7}/) {
bad_line("unresolved merge conflict", $_);
}
}
}
exit($found_bad);
......
......@@ -115,3 +115,53 @@ void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callb
free(entry);
}
static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode)
{
int namelen = strlen(name);
while (t->size) {
const char *entry;
const unsigned char *sha1;
int entrylen, cmp;
sha1 = tree_entry_extract(t, &entry, mode);
update_tree_entry(t);
entrylen = strlen(entry);
if (entrylen > namelen)
continue;
cmp = memcmp(name, entry, entrylen);
if (cmp > 0)
continue;
if (cmp < 0)
break;
if (entrylen == namelen) {
memcpy(result, sha1, 20);
return 0;
}
if (name[entrylen] != '/')
continue;
if (!S_ISDIR(*mode))
break;
if (++entrylen == namelen) {
memcpy(result, sha1, 20);
return 0;
}
return get_tree_entry(sha1, name + entrylen, result, mode);
}
return -1;
}
int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned char *sha1, unsigned *mode)
{
int retval;
void *tree;
struct tree_desc t;
tree = read_object_with_reference(tree_sha1, tree_type, &t.size, NULL);
if (!tree)
return -1;
t.buf = tree;
retval = find_tree_entry(&t, name, sha1, mode);
free(tree);
return retval;
}
......@@ -22,4 +22,6 @@ typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry
void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callback_t callback);
int get_tree_entry(const unsigned char *, const char *, unsigned char *, unsigned *);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册