diff --git a/Documentation/git-commit-script.txt b/Documentation/git-commit-script.txt new file mode 100644 index 0000000000..bb559d70a5 --- /dev/null +++ b/Documentation/git-commit-script.txt @@ -0,0 +1,49 @@ +git-commit-script(1) +==================== +v0.99.4, Aug 2005 + +NAME +---- +git-commit-script - Record your changes + +SYNOPSIS +-------- +'git commit' [-a] [(-c | -C) | -F | -m ] ... + +DESCRIPTION +----------- +Updates the index file for given paths, or all modified files if +'-a' is specified, and makes a commit object. The command +VISUAL and EDITOR environment variables to edit the commit log +message. + +OPTIONS +------- +-a:: + Update all paths in the index file. + +-c or -C :: + Take existing commit object, and reuse the log message + and the authorship information (including the timestamp) + when creating the commit. With '-C', the editor is not + invoked; with '-c' the user can further edit the commit + message. + +-F :: + Take the commit message from the given file. Use '-' to + read the message from the standard input. + +-m :: + Use the given as the commit message. + +...:: + Update specified paths in the index file. + + +Author +------ +Written by Linus Torvalds + +GIT +--- +Part of the link:git.html[git] suite diff --git a/Documentation/git-ls-remote-script.txt b/Documentation/git-ls-remote-script.txt new file mode 100644 index 0000000000..0b98e6a9f4 --- /dev/null +++ b/Documentation/git-ls-remote-script.txt @@ -0,0 +1,64 @@ +git-ls-remote-script(1) +======================= +v0.1, May 2005 + +NAME +---- +git-ls-remote-script - Look at references other repository has. + + +SYNOPSIS +-------- +'git-ls-remote' [--heads] [--tags] ... + +DESCRIPTION +----------- +Displays the references other repository has. + + +OPTIONS +------- +--heads --tags:: + Limit to only refs/heads and refs/tags, respectively. + These options are _not_ mutually exclusive; when given + both, references stored in refs/heads and refs/tags are + displayed. + +:: + Location of the repository. The shorthand defined in + $GIT_DIR/branches/ can be used. + +...:: + When unspecified, all references, after filtering done + with --heads and --tags, are shown. When ... are + specified, only references matching the given patterns + are displayed. + +EXAMPLES +-------- + + $ git ls-remote --tags ./. + d6602ec5194c87b0fc87103ca4d67251c76f233a refs/tags/v0.99 + f25a265a342aed6041ab0cc484224d9ca54b6f41 refs/tags/v0.99.1 + 7ceca275d047c90c0c7d5afb13ab97efdf51bd6e refs/tags/v0.99.3 + c5db5456ae3b0873fc659c19fafdde22313cc441 refs/tags/v0.99.2 + 0918385dbd9656cab0d1d81ba7453d49bbc16250 refs/tags/junio-gpg-pub + $ git ls-remote http://www.kernel.org/pub/scm/git/git.git master pu rc + 5fe978a5381f1fbad26a80e682ddd2a401966740 refs/heads/master + c781a84b5204fb294c9ccc79f8b3baceeb32c061 refs/heads/pu + b1d096f2926c4e37c9c0b6a7bf2119bedaa277cb refs/heads/rc + $ echo http://www.kernel.org/pub/scm/git/git.git >.git/branches/public + $ git ls-remote --tags public v\* + d6602ec5194c87b0fc87103ca4d67251c76f233a refs/tags/v0.99 + f25a265a342aed6041ab0cc484224d9ca54b6f41 refs/tags/v0.99.1 + c5db5456ae3b0873fc659c19fafdde22313cc441 refs/tags/v0.99.2 + 7ceca275d047c90c0c7d5afb13ab97efdf51bd6e refs/tags/v0.99.3 + +Author +------ +Written by Junio C Hamano + +GIT +--- +Part of the link:git.html[git] suite + diff --git a/Documentation/git.txt b/Documentation/git.txt index d18cf5ec16..1308eb675d 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -34,6 +34,10 @@ the repository, the cache and the working fileset, those that interrogate and compare them, and those that moves objects and references between repositories. +In addition, git itself comes with a spartan set of porcelain +commands. They are usable but are not meant to compete with real +Porcelains. + There are also some ancilliary programs that can be viewed as useful aids for using the core commands but which are unlikely to be used by SCMs layered over git. @@ -128,14 +132,6 @@ link:git-clone-pack.html[git-clone-pack]:: Clones a repository into the current repository (engine for ssh and local transport) -link:git-fetch-script.html[git-fetch-script]:: - Download from a remote repository via various protocols - (user interface). - -link:git-pull-script.html[git-pull-script]:: - Fetch from and merge with a remote repository via - various protocols (user interface). - link:git-http-pull.html[git-http-pull]:: Downloads a remote GIT repository via HTTP @@ -169,6 +165,18 @@ link:git-update-server-info.html[git-update-server-info]:: clients discover references and packs on it. +Porcelainish Commands +--------------------- +link:git-fetch-script.html[git-fetch-script]:: + Download from a remote repository via various protocols. + +link:git-pull-script.html[git-pull-script]:: + Fetch from and merge with a remote repository. + +link:git-commit-script.html[git-commit-script]:: + Record changes to the repository. + + Ancilliary Commands ------------------- Manipulators: diff --git a/Makefile b/Makefile index df5f8c0dc3..e0ea88fbae 100644 --- a/Makefile +++ b/Makefile @@ -70,6 +70,7 @@ SCRIPTS=git git-apply-patch-script git-merge-one-file-script git-prune-script \ SCRIPTS += git-count-objects-script # SCRIPTS += git-send-email-script +SCRIPTS += git-revert-script PROG= git-update-cache git-diff-files git-init-db git-write-tree \ git-read-tree git-commit-tree git-cat-file git-fsck-cache \ diff --git a/apply.c b/apply.c index c671d9e86c..81607c0fb6 100644 --- a/apply.c +++ b/apply.c @@ -563,7 +563,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc struct fragment dummy; if (parse_fragment_header(line, len, &dummy) < 0) continue; - error("patch fragment without header at line %d: %.*s", linenr, len-1, line); + error("patch fragment without header at line %d: %.*s", linenr, (int)len-1, line); } if (size < len + 6) @@ -968,7 +968,7 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch) while (frag) { if (apply_one_fragment(desc, frag) < 0) - return error("patch failed: %s:%d", patch->old_name, frag->oldpos); + return error("patch failed: %s:%ld", patch->old_name, frag->oldpos); frag = frag->next; } return 0; diff --git a/cache.h b/cache.h index 957e2ca7ca..efd2a2c595 100644 --- a/cache.h +++ b/cache.h @@ -40,6 +40,10 @@ #define NORETURN #endif +#ifndef __attribute__ +#define __attribute(x) +#endif + /* * Intensive research over the course of many years has shown that * port 9418 is totally unused by anything else. Or @@ -171,8 +175,8 @@ extern void rollback_index_file(struct cache_file *); #define TYPE_CHANGED 0x0040 /* Return a statically allocated filename matching the sha1 signature */ -extern char *mkpath(const char *fmt, ...); -extern char *git_path(const char *fmt, ...); +extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern char *sha1_file_name(const unsigned char *sha1); extern char *sha1_pack_name(const unsigned char *sha1); extern char *sha1_pack_index_name(const unsigned char *sha1); @@ -218,8 +222,8 @@ extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ /* General helper functions */ extern void usage(const char *err) NORETURN; -extern void die(const char *err, ...) NORETURN; -extern int error(const char *err, ...); +extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); +extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2); diff --git a/clone-pack.c b/clone-pack.c index e9c20dee71..49820c6579 100644 --- a/clone-pack.c +++ b/clone-pack.c @@ -30,7 +30,7 @@ static int is_master(struct ref *ref) static void write_one_ref(struct ref *ref) { - char *path = git_path(ref->name); + char *path = git_path("%s", ref->name); int fd; char *hex; diff --git a/commit.c b/commit.c index 3ac421ac34..59e93d4590 100644 --- a/commit.c +++ b/commit.c @@ -33,6 +33,8 @@ enum cmit_fmt get_commit_format(const char *arg) return CMIT_FMT_SHORT; if (!strcmp(arg, "=full")) return CMIT_FMT_FULL; + if (!strcmp(arg, "=oneline")) + return CMIT_FMT_ONELINE; die("invalid --pretty format"); } @@ -350,6 +352,8 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c unsigned long time; int tz, ret; + if (fmt == CMIT_FMT_ONELINE) + return 0; date = strchr(line, '>'); if (!date) return 0; @@ -373,6 +377,9 @@ static int is_empty_line(const char *line, int len) static int add_parent_info(enum cmit_fmt fmt, char *buf, const char *line, int parents) { int offset = 0; + + if (fmt == CMIT_FMT_ONELINE) + return offset; switch (parents) { case 1: break; @@ -393,6 +400,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned l int hdr = 1, body = 0; unsigned long offset = 0; int parents = 0; + int indent = (fmt == CMIT_FMT_ONELINE) ? 0 : 4; for (;;) { const char *line = msg; @@ -416,7 +424,8 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned l if (hdr) { if (linelen == 1) { hdr = 0; - buf[offset++] = '\n'; + if (fmt != CMIT_FMT_ONELINE) + buf[offset++] = '\n'; continue; } if (fmt == CMIT_FMT_RAW) { @@ -446,13 +455,23 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned l } else { body = 1; } - memset(buf + offset, ' ', 4); - memcpy(buf + offset + 4, line, linelen); - offset += linelen + 4; + + memset(buf + offset, ' ', indent); + memcpy(buf + offset + indent, line, linelen); + offset += linelen + indent; + if (fmt == CMIT_FMT_ONELINE) + break; + } + if (fmt == CMIT_FMT_ONELINE) { + /* We do not want the terminating newline */ + if (buf[offset - 1] == '\n') + offset--; + } + else { + /* Make sure there is an EOLN */ + if (buf[offset - 1] != '\n') + buf[offset++] = '\n'; } - /* Make sure there is an EOLN */ - if (buf[offset - 1] != '\n') - buf[offset++] = '\n'; buf[offset] = '\0'; return offset; } diff --git a/commit.h b/commit.h index c24ab21061..5d179d4dc8 100644 --- a/commit.h +++ b/commit.h @@ -40,6 +40,7 @@ enum cmit_fmt { CMIT_FMT_DEFAULT = CMIT_FMT_MEDIUM, CMIT_FMT_SHORT, CMIT_FMT_FULL, + CMIT_FMT_ONELINE, }; extern enum cmit_fmt get_commit_format(const char *arg); diff --git a/connect.c b/connect.c index 20b80a1b54..a6657b1384 100644 --- a/connect.c +++ b/connect.c @@ -166,7 +166,8 @@ static int match_explicit_refs(struct ref *src, struct ref *dst, if (matched_src) break; errs = 1; - error("src refspec %s does not match any."); + error("src refspec %s does not match any.", + rs[i].src); break; default: errs = 1; @@ -381,8 +382,15 @@ int git_connect(int fd[2], char *url, const char *prog) close(pipefd[0][1]); close(pipefd[1][0]); close(pipefd[1][1]); - if (protocol == PROTO_SSH) - execlp("ssh", "ssh", host, command, NULL); + if (protocol == PROTO_SSH) { + const char *ssh = getenv("GIT_SSH") ? : "ssh"; + const char *ssh_basename = strrchr(ssh, '/'); + if (!ssh_basename) + ssh_basename = ssh; + else + ssh_basename++; + execlp(ssh, ssh_basename, host, command, NULL); + } else execlp("sh", "sh", "-c", command, NULL); die("exec failed"); diff --git a/convert-cache.c b/convert-cache.c index 8916a3692f..95f0302f7a 100644 --- a/convert-cache.c +++ b/convert-cache.c @@ -60,7 +60,7 @@ static void convert_ascii_sha1(void *buffer) struct entry *entry; if (get_sha1_hex(buffer, sha1)) - die("expected sha1, got '%s'", buffer); + die("expected sha1, got '%s'", (char*) buffer); entry = convert_entry(sha1); memcpy(buffer, sha1_to_hex(entry->new_sha1), 40); } @@ -272,7 +272,7 @@ static void convert_commit(void *buffer, unsigned long size, unsigned char *resu unsigned long orig_size = size; if (memcmp(buffer, "tree ", 5)) - die("Bad commit '%s'", buffer); + die("Bad commit '%s'", (char*) buffer); convert_ascii_sha1(buffer+5); buffer += 46; /* "tree " + "hex sha1" + "\n" */ while (!memcmp(buffer, "parent ", 7)) { diff --git a/csum-file.h b/csum-file.h index 776cfb152a..3ad1a992a7 100644 --- a/csum-file.h +++ b/csum-file.h @@ -11,7 +11,7 @@ struct sha1file { }; extern struct sha1file *sha1fd(int fd, const char *name); -extern struct sha1file *sha1create(const char *fmt, ...); +extern struct sha1file *sha1create(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern int sha1close(struct sha1file *, unsigned char *, int); extern int sha1write(struct sha1file *, void *, unsigned int); extern int sha1write_compressed(struct sha1file *, void *, unsigned int); diff --git a/diff.c b/diff.c index 9962fc359c..3e52fec187 100644 --- a/diff.c +++ b/diff.c @@ -134,8 +134,8 @@ static void builtin_diff(const char *name_a, int complete_rewrite) { int i, next_at, cmd_size; - const char *diff_cmd = "diff -L%s%s -L%s%s"; - const char *diff_arg = "%s %s||:"; /* "||:" is to return 0 */ + const char *const diff_cmd = "diff -L%s%s -L%s%s"; + const char *const diff_arg = "%s %s||:"; /* "||:" is to return 0 */ const char *input_name_sq[2]; const char *path0[2]; const char *path1[2]; @@ -782,7 +782,8 @@ static void diff_flush_raw(struct diff_filepair *p, char status[10]; if (line_termination) { - const char *err = "path %s cannot be expressed without -z"; + const char *const err = + "path %s cannot be expressed without -z"; if (strchr(p->one->path, line_termination) || strchr(p->one->path, inter_name_termination)) die(err, p->one->path); diff --git a/git-cherry b/git-cherry index f3bfbf3a4e..e186363647 100755 --- a/git-cherry +++ b/git-cherry @@ -3,7 +3,9 @@ # Copyright (c) 2005 Junio C Hamano. # -usage="usage: $0 "' [] +. git-sh-setup-script || die "Not a git archive." + +usage="usage: $0 "'[-v] [] __*__*__*__*__> / @@ -18,29 +20,38 @@ upstream, it is shown on the standard output. The output is intended to be used as: OLD_HEAD=$(git-rev-parse HEAD) - git-rev-parse linus >${GIT_DIR-.}/HEAD - git-cherry linus OLD_HEAD | + git-rev-parse upstream >${GIT_DIR-.}/HEAD + git-cherry upstream $OLD_HEAD | while read commit do GIT_EXTERNAL_DIFF=git-apply-patch-script git-diff-tree -p "$commit" && - git-commit-script -m "$commit" + git-commit-script -C "$commit" done ' +case "$1" in -v) verbose=t; shift ;; esac + +case "$#,$1" in +1,*..*) + upstream=$(expr "$1" : '\(.*\)\.\.') ours=$(expr "$1" : '.*\.\.\(.*\)$') + set x "$upstream" "$ours" + shift ;; +esac + case "$#" in -1) linus=`git-rev-parse --verify "$1"` && - junio=`git-rev-parse --verify HEAD` || exit +1) upstream=`git-rev-parse --verify "$1"` && + ours=`git-rev-parse --verify HEAD` || exit ;; -2) linus=`git-rev-parse --verify "$1"` && - junio=`git-rev-parse --verify "$2"` || exit +2) upstream=`git-rev-parse --verify "$1"` && + ours=`git-rev-parse --verify "$2"` || exit ;; *) echo >&2 "$usage"; exit 1 ;; esac # Note that these list commits in reverse order; # not that the order in inup matters... -inup=`git-rev-list ^$junio $linus` && -ours=`git-rev-list $junio ^$linus` || exit +inup=`git-rev-list ^$ours $upstream` && +ours=`git-rev-list $ours ^$upstream` || exit tmp=.cherry-tmp$$ patch=$tmp-patch @@ -74,6 +85,10 @@ do else sign=+ fi + case "$verbose" in + t) + c=$(git-rev-list --pretty=oneline --max-count=1 $c) + esac case "$O" in '') O="$sign $c" ;; *) O="$sign $c$LF$O" ;; diff --git a/git-commit-script b/git-commit-script index 1d59f46b94..24ec446a9d 100755 --- a/git-commit-script +++ b/git-commit-script @@ -6,44 +6,105 @@ . git-sh-setup-script || die "Not a git archive" usage () { - die 'git commit [--all] [-m existing-commit] [...]' + die 'git commit [-a] [-m ] [-F ] [(-C|-c) ] [...]' } -files=() -while case "$#" in 0) break ;; esac +all= logfile= use_commit= no_edit= log_given= log_message= +while case "$#" in 0) break;; esac do - case "$1" in - -m) shift - case "$#" in - 0) usage ;; - *) use_commit=`git-rev-parse --verify "$1"` || - exit ;; - esac - ;; - --all) - files=($(git-diff-files --name-only))\ - ;; - *) break - ;; - esac + case "$1" in + -a|--a|--al|--all) + all=t + shift ;; + -F=*|--f=*|--fi=*|--fil=*|--file=*) + log_given=t$log_given + logfile=`expr "$1" : '-[^=]*=\(.*\)'` + no_edit=t + shift ;; + -F|--f|--fi|--fil|--file) + case "$#" in 1) usage ;; esac; shift + log_given=t$log_given + logfile="$1" + no_edit=t + shift ;; + -m=*|--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*) + log_given=t$log_given + log_message=`expr "$1" : '-[^=]*=\(.*\)'` + no_edit=t + shift ;; + -m|--m|--me|--mes|--mess|--messa|--messag|--message) + case "$#" in 1) usage ;; esac; shift + log_given=t$log_given + log_message="$1" + no_edit=t + shift ;; + -c=*|--ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\ + --reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\ + --reedit-messag=*|--reedit-message=*) + log_given=t$log_given + use_commit=`expr "$1" : '-[^=]*=\(.*\)'` + shift ;; + -c|--ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\ + --reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|--reedit-message) + case "$#" in 1) usage ;; esac; shift + log_given=t$log_given + use_commit="$1" + shift ;; + -C=*|--reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\ + --reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\ + --reuse-message=*) + log_given=t$log_given + use_commit=`expr "$1" : '-[^=]*=\(.*\)'` + no_edit=t + shift ;; + -C|--reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\ + --reuse-mess|--reuse-messa|--reuse-messag|--reuse-message) + case "$#" in 1) usage ;; esac; shift + log_given=t$log_given + use_commit="$1" + no_edit=t + shift ;; + --) shift + break ;; + -*) + usage ;; + *) + break ;; + esac done -git-update-cache -q --refresh -- "$@" "${files[@]}" || exit 1 +case "$log_given" in +tt*) + die "Only one of -c/-C/-F/-m can be used." ;; +esac + +case "$all" in +t) + git-diff-files --name-only -z | + xargs -0 git-update-cache -q -- || exit 1 ;; +esac +git-update-cache -q --refresh -- "$@" || exit 1 + PARENTS="-p HEAD" if [ ! -r "$GIT_DIR/HEAD" ]; then if [ -z "$(git-ls-files)" ]; then echo Nothing to commit 1>&2 exit 1 fi - ( + { echo "#" echo "# Initial commit" + case "$no_edit" in + t) echo "# (ignoring your commit message for initial commit)" + no_edit= + esac echo "#" git-ls-files | sed 's/^/# New file: /' echo "#" - ) > .editmsg + } >.editmsg PARENTS="" + no_edit= else if [ -f "$GIT_DIR/MERGE_HEAD" ]; then echo "#" @@ -51,8 +112,25 @@ else echo "# If this is not correct, please remove the file" echo "# $GIT_DIR/MERGE_HEAD" echo "# and try again" + case "$no_edit" in + t) echo "# (ignoring your commit message for merge commit)" + no_edit= + esac echo "#" PARENTS="-p HEAD -p MERGE_HEAD" + elif test "$log_message" != '' + then + echo "$log_message" + elif test "$logfile" != "" + then + if test "$logfile" = - + then + test -t 0 && + echo >&2 "(reading log message from standard input)" + cat + else + cat <"$logfile" + fi elif test "$use_commit" != "" then pick_author_script=' @@ -92,17 +170,22 @@ then rm .editmsg exit 1 fi -case "$use_commit" in +case "$no_edit" in '') ${VISUAL:-${EDITOR:-vi}} .editmsg ;; esac grep -v '^#' < .editmsg | git-stripspace > .cmitmsg -[ -s .cmitmsg ] && +if test -s .cmitmsg +then tree=$(git-write-tree) && commit=$(cat .cmitmsg | git-commit-tree $tree $PARENTS) && echo $commit > "$GIT_DIR/HEAD" && rm -f -- "$GIT_DIR/MERGE_HEAD" +else + echo >&2 "* no commit message? aborting commit." + false +fi ret="$?" rm -f .cmitmsg .editmsg exit "$ret" diff --git a/git-format-patch-script b/git-format-patch-script index 51e8af0acb..c0081697da 100755 --- a/git-format-patch-script +++ b/git-format-patch-script @@ -3,6 +3,8 @@ # Copyright (c) 2005 Junio C Hamano # +. git-sh-setup-script || die "Not a git archive." + usage () { echo >&2 "usage: $0"' [-n] [-o dir] [--mbox] [--check] [-...] upstream [ our-head ] @@ -60,13 +62,20 @@ do shift done +revpair= case "$#" in -2) linus="$1" junio="$2" ;; -1) linus="$1" junio=HEAD ;; -*) usage ;; +2) + revpair="$1..$2" ;; +1) + case "$1" in + *..*) + revpair="$1";; + *) + revpair="$1..HEAD";; + esac ;; +*) + usage ;; esac -junio=`git-rev-parse --verify "$junio"` -linus=`git-rev-parse --verify "$linus"` me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'` @@ -108,7 +117,8 @@ _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" stripCommitHead='/^'"$_x40"' (from '"$_x40"')$/d' -git-rev-list --merge-order "$junio" "^$linus" >$series +git-rev-list --no-merges --merge-order \ + $(git-rev-parse --revs-only "$revpair") >$series total=`wc -l <$series | tr -dc "[0-9]"` i=$total while read commit diff --git a/git-ls-remote-script b/git-ls-remote-script index 31cdac8bfe..75f6027866 100755 --- a/git-ls-remote-script +++ b/git-ls-remote-script @@ -3,7 +3,7 @@ . git-sh-setup-script || die "Not a git archive" usage () { - echo >&2 "usage: $0 [--heads] [--tags] [--overwrite | --store] repo" + echo >&2 "usage: $0 [--heads] [--tags] ..." exit 1; } @@ -12,10 +12,6 @@ do case "$1" in -h|--h|--he|--hea|--head|--heads) heads=heads; shift ;; - -o|--o|--ov|--ove|--over|--overw|--overwr|--overwri|--overwrit|--overwrite) - overwrite=overwrite; shift ;; - -s|--s|--st|--sto|--stor|--store) - store=store; shift ;; -t|--t|--ta|--tag|--tags) tags=tags; shift ;; --) @@ -27,15 +23,15 @@ do esac done -case "$#" in 1) ;; *) usage ;; esac -case ",$store,$overwrite," in *,,*) ;; *) usage ;; esac +case "$#" in 0) usage ;; esac case ",$heads,$tags," in ,,,) heads=heads tags=tags other=other ;; esac -. git-parse-remote "$@" +. git-parse-remote "$1" peek_repo="$_remote_repo" +shift tmp=.ls-remote-$$ trap "rm -fr $tmp-*" 0 1 2 3 15 @@ -65,7 +61,7 @@ rsync://* ) git-peek-remote "$peek_repo" ;; esac | - +sort -t ' ' -k 2 | while read sha1 path do case "$path" in @@ -82,23 +78,23 @@ do *) continue;; esac - - echo "$sha1 $path" - - case "$path,$store,$overwrite," in - *,,, | HEAD,*) continue ;; + case "$#" in + 0) + match=yes ;; + *) + match=no + for pat + do + case "/$path" in + */$pat ) + match=yes + break ;; + esac + done esac - - if test -f "$GIT_DIR/$path" && test "$overwrite" == "" - then - continue - fi - - # Be careful. We may not have that object yet! - if git-cat-file -t "$sha1" >/dev/null 2>&1 - then - echo "$sha1" >"$GIT_DIR/$path" - else - echo >&2 "* You have not fetched updated $path ($sha1)." - fi + case "$match" in + no) + continue ;; + esac + echo "$sha1 $path" done diff --git a/git-push-script b/git-push-script index 80e922bb5d..70fa9684a5 100755 --- a/git-push-script +++ b/git-push-script @@ -1,3 +1,64 @@ #!/bin/sh . git-sh-setup-script || die "Not a git archive" -git-send-pack "$@" + +# Parse out parameters and then stop at remote, so that we can +# translate it using .git/branches information +has_all= +has_force= +has_exec= +remote= + +while case "$#" in 0) break ;; esac +do + case "$1" in + --all) + has_all=--all ;; + --force) + has_force=--force ;; + --exec=*) + has_exec="$1" ;; + -*) + die "Unknown parameter $1" ;; + *) + remote="$1" + shift + set x "$@" + shift + break ;; + esac + shift +done + +case "$remote" in +*:* | /* | ../* | ./* ) + # An URL, host:/path/to/git, absolute and relative paths. + ;; +* ) + # Shorthand + if expr "$remote" : '..*/..*' >/dev/null + then + # a short-hand followed by a trailing path + shorthand=$(expr "$remote" : '\([^/]*\)') + remainder=$(expr "$remote" : '[^/]*\(/.*\)$') + else + shorthand="$remote" + remainder= + fi + remote=$(sed -e 's/#.*//' "$GIT_DIR/branches/$remote") && + expr "$remote" : '..*:' >/dev/null && + remote="$remote$remainder" || + die "Cannot parse remote $remote" + ;; +esac + +case "$remote" in +http://* | https://* | git://* | rsync://* ) + die "Cannot push to $remote" ;; +esac + +set x "$remote" "$@"; shift +test "$has_all" && set x "$has_all" "$@" && shift +test "$has_force" && set x "$has_force" "$@" && shift +test "$has_exec" && set x "$has_exec" "$@" && shift + +exec git-send-pack "$@" diff --git a/git-rebase-script b/git-rebase-script index 5b791c6bda..7779813d11 100755 --- a/git-rebase-script +++ b/git-rebase-script @@ -3,25 +3,32 @@ # Copyright (c) 2005 Junio C Hamano. # +. git-sh-setup-script || die "Not a git archive." + usage="usage: $0 "' [] Uses output from git-cherry to rebase local commits to the new head of upstream tree.' -: ${GIT_DIR=.git} +case "$#,$1" in +1,*..*) + upstream=$(expr "$1" : '\(.*\)\.\.') ours=$(expr "$1" : '.*\.\.\(.*\)$') + set x "$upstream" "$ours" + shift ;; +esac case "$#" in -1) linus=`git-rev-parse --verify "$1"` && - junio=`git-rev-parse --verify HEAD` || exit +1) upstream=`git-rev-parse --verify "$1"` && + ours=`git-rev-parse --verify HEAD` || exit ;; -2) linus=`git-rev-parse --verify "$1"` && - junio=`git-rev-parse --verify "$2"` || exit +2) upstream=`git-rev-parse --verify "$1"` && + ours=`git-rev-parse --verify "$2"` || exit ;; *) echo >&2 "$usage"; exit 1 ;; esac -git-read-tree -m -u $junio $linus && -echo "$linus" >"$GIT_DIR/HEAD" || exit +git-read-tree -m -u $ours $upstream && +echo "$upstream" >"$GIT_DIR/HEAD" || exit tmp=.rebase-tmp$$ fail=$tmp-fail @@ -29,7 +36,7 @@ trap "rm -rf $tmp-*" 0 1 2 3 15 >$fail -git-cherry $linus $junio | +git-cherry $upstream $ours | while read sign commit do case "$sign" in @@ -37,7 +44,7 @@ do esac S=`cat "$GIT_DIR/HEAD"` && GIT_EXTERNAL_DIFF=git-apply-patch-script git-diff-tree -p $commit && - git-commit-script -m "$commit" || { + git-commit-script -C "$commit" || { echo $commit >>$fail git-read-tree --reset -u $S } diff --git a/git-reset-script b/git-reset-script index b6476edc30..49994df7a2 100755 --- a/git-reset-script +++ b/git-reset-script @@ -2,6 +2,12 @@ . git-sh-setup-script || die "Not a git archive" rev=$(git-rev-parse --revs-only --verify --default HEAD "$@") || exit rev=$(git-rev-parse --revs-only --verify $rev^0) || exit -git-read-tree --reset "$rev" && echo "$rev" > "$GIT_DIR/HEAD" +git-read-tree --reset "$rev" && { + if orig=$(git-rev-parse --verify HEAD 2>/dev/null) + then + echo "$orig" >"$GIT_DIR/ORIG_HEAD" + fi + echo "$rev" > "$GIT_DIR/HEAD" +} git-update-cache --refresh rm -f "$GIT_DIR/MERGE_HEAD" diff --git a/git-revert-script b/git-revert-script new file mode 100755 index 0000000000..dc2dea4898 --- /dev/null +++ b/git-revert-script @@ -0,0 +1,37 @@ +#!/bin/sh +. git-sh-setup-script || die "Not a git archive" + +# We want a clean tree and clean index to be able to revert. +status=$(git status) +case "$status" in +'nothing to commit') ;; +*) + echo "$status" + die "Your working tree is dirty; cannot revert a previous patch." ;; +esac + +rev=$(git-rev-parse --no-flags --verify --revs-only "$@") && +commit=$(git-rev-parse --verify "$rev^0") || exit +if git-diff-tree -R -M -p $commit | git-apply --index && + msg=$(git-rev-list --pretty=oneline --max-count=1 $commit) +then + { + echo "$msg" | sed -e ' + s/^[^ ]* /Revert "/ + s/$/"/' + echo + echo "This reverts $commit commit." + test "$rev" = "$commit" || + echo "(original 'git revert' arguments: $@)" + } | git commit -F - +else + # Now why did it fail? + parents=`git-cat-file commit "$commit" 2>/dev/null | + sed -ne '/^$/q;/^parent /p' | + wc -l` + case $parents in + 0) die "Cannot revert the root commit nor non commit-ish." ;; + 1) die "The patch does not apply." ;; + *) die "Cannot revert a merge commit." ;; + esac +fi diff --git a/pack-check.c b/pack-check.c index 054b0131e9..511f29424a 100644 --- a/pack-check.c +++ b/pack-check.c @@ -15,7 +15,7 @@ static int verify_packfile(struct packed_git *p) /* Header consistency check */ hdr = p->pack_base; if (hdr->hdr_signature != htonl(PACK_SIGNATURE)) - return error("Packfile signature mismatch", p->pack_name); + return error("Packfile %s signature mismatch", p->pack_name); if (hdr->hdr_version != htonl(PACK_VERSION)) return error("Packfile version %d different from ours %d", ntohl(hdr->hdr_version), PACK_VERSION); diff --git a/pkt-line.h b/pkt-line.h index b0b4f6d495..51d0cbe219 100644 --- a/pkt-line.h +++ b/pkt-line.h @@ -5,7 +5,7 @@ * Silly packetized line writing interface */ void packet_flush(int fd); -void packet_write(int fd, const char *fmt, ...); +void packet_write(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3))); int packet_read_line(int fd, char *buffer, unsigned size); diff --git a/refs.c b/refs.c index 774f1630fe..a5c8946610 100644 --- a/refs.c +++ b/refs.c @@ -6,7 +6,7 @@ static int read_ref(const char *refname, unsigned char *sha1) { int ret = -1; - int fd = open(git_path(refname), O_RDONLY); + int fd = open(git_path("%s", refname), O_RDONLY); if (fd >= 0) { char buffer[60]; @@ -20,7 +20,7 @@ static int read_ref(const char *refname, unsigned char *sha1) static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1)) { int retval = 0; - DIR *dir = opendir(git_path(base)); + DIR *dir = opendir(git_path("%s", base)); if (dir) { struct dirent *de; @@ -46,7 +46,7 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, const u if (namelen > 255) continue; memcpy(path + baselen, de->d_name, namelen+1); - if (lstat(git_path(path), &st) < 0) + if (lstat(git_path("%s", path), &st) < 0) continue; if (S_ISDIR(st.st_mode)) { retval = do_for_each_ref(path, fn); diff --git a/rev-list.c b/rev-list.c index fae30a2b68..ce5b8b2ad5 100644 --- a/rev-list.c +++ b/rev-list.c @@ -15,12 +15,15 @@ static const char rev_list_usage[] = " --max-count=nr\n" " --max-age=epoch\n" " --min-age=epoch\n" + " --parents\n" " --bisect\n" " --objects\n" " --unpacked\n" " --header\n" " --pretty\n" - " --merge-order [ --show-breaks ]"; + " --no-merges\n" + " --merge-order [ --show-breaks ]\n" + " --topo-order"; static int unpacked = 0; static int bisect_list = 0; @@ -39,6 +42,7 @@ static int merge_order = 0; static int show_breaks = 0; static int stop_traversal = 0; static int topo_order = 0; +static int no_merges = 0; static void show_commit(struct commit *commit) { @@ -59,7 +63,11 @@ static void show_commit(struct commit *commit) parents = parents->next; } } - putchar('\n'); + if (commit_format == CMIT_FMT_ONELINE) + putchar(' '); + else + putchar('\n'); + if (verbose_header) { static char pretty_header[16384]; pretty_print_commit(commit_format, commit->buffer, ~0, pretty_header, sizeof(pretty_header)); @@ -82,6 +90,8 @@ static int filter_commit(struct commit * commit) } if (max_count != -1 && !max_count--) return STOP; + if (no_merges && (commit->parents && commit->parents->next)) + return CONTINUE; return DO; } @@ -497,7 +507,14 @@ int main(int argc, char **argv) commit_format = get_commit_format(arg+8); verbose_header = 1; hdr_termination = '\n'; - prefix = "commit "; + if (commit_format == CMIT_FMT_ONELINE) + prefix = ""; + else + prefix = "commit "; + continue; + } + if (!strncmp(arg, "--no-merges", 11)) { + no_merges = 1; continue; } if (!strcmp(arg, "--parents")) { diff --git a/rev-parse.c b/rev-parse.c index 1965e90a8a..1c6ae76f9a 100644 --- a/rev-parse.c +++ b/rev-parse.c @@ -33,6 +33,9 @@ static int is_rev_argument(const char *arg) "--max-age=", "--min-age=", "--merge-order", + "--topo-order", + "--bisect", + "--no-merges", NULL }; const char **p = rev_args; diff --git a/rsh.c b/rsh.c index fe87e581d2..bcb1c80d84 100644 --- a/rsh.c +++ b/rsh.c @@ -56,10 +56,16 @@ int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, return error("Couldn't create socket"); } if (!fork()) { + const char *ssh = getenv("GIT_SSH") ? : "ssh"; + const char *ssh_basename = strrchr(ssh, '/'); + if (!ssh_basename) + ssh_basename = ssh; + else + ssh_basename++; close(sv[1]); dup2(sv[0], 0); dup2(sv[0], 1); - execlp("ssh", "ssh", host, command, NULL); + execlp(ssh, ssh_basename, host, command, NULL); } close(sv[0]); *fd_in = sv[1]; diff --git a/sha1_file.c b/sha1_file.c index e9285c144e..8d189d4919 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1388,7 +1388,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, ssize_t size; if (*bufposn) { stream.avail_in = *bufposn; - stream.next_in = buffer; + stream.next_in = (unsigned char *) buffer; do { stream.next_out = discard; stream.avail_out = sizeof(discard); diff --git a/tar-tree.c b/tar-tree.c index a877fe545e..2716ae3eb1 100644 --- a/tar-tree.c +++ b/tar-tree.c @@ -325,8 +325,8 @@ static void write_header(const unsigned char *sha1, char typeflag, const char *b memcpy(&header[257], "ustar", 6); memcpy(&header[263], "00", 2); - printf(&header[329], "%07o", 0); /* devmajor */ - printf(&header[337], "%07o", 0); /* devminor */ + sprintf(&header[329], "%07o", 0); /* devmajor */ + sprintf(&header[337], "%07o", 0); /* devminor */ memset(&header[148], ' ', 8); for (i = 0; i < RECORDSIZE; i++) diff --git a/tools/mailsplit.c b/tools/mailsplit.c index 7b712081cb..a3238c20da 100644 --- a/tools/mailsplit.c +++ b/tools/mailsplit.c @@ -77,7 +77,7 @@ static int parse_email(const void *map, unsigned long size) /* * Search for a line beginning with "From ", and - * having smething that looks like a date format. + * having something that looks like a date format. */ do { int len = linelen(map, size);