diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 0e502ae68d..a25d04a4fa 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -8,7 +8,9 @@ -t, \--tags:: By default, the git core utilities will not fetch and store tags under the same name as the remote repository; ask it - to do so using `--tags`. + to do so using `--tags`. Using this option will bound the + list of objects pulled to the remote tags. Commits in branches + beyond the tags will be ignored. -u, \--update-head-ok:: By default `git-fetch` refuses to update the head which diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt index 2e23cbc0f5..9fe86aef98 100644 --- a/Documentation/git-pack-redundant.txt +++ b/Documentation/git-pack-redundant.txt @@ -16,6 +16,14 @@ This program computes which packs in your repository are redundant. The output is suitable for piping to 'xargs rm' if you are in the root of the repository. +git-pack-redundant accepts a list of objects on standard input. Any objects +given will be ignored when checking which packs are required. This makes the +following command useful when wanting to remove packs which contain unreachable +objects. + +git-fsck-objects --full --unreachable | cut -d ' ' -f3 | \ +git-pack-redundant --all | xargs rm + OPTIONS ------- diff --git a/Makefile b/Makefile index 819c48ce8b..2d8853d69e 100644 --- a/Makefile +++ b/Makefile @@ -208,6 +208,10 @@ endif ifeq ($(uname_O),Cygwin) NO_STRCASESTR = YesPlease NEEDS_LIBICONV = YesPlease + # There are conflicting reports about this. + # On some boxes NO_MMAP is needed, and not so elsewhere. + # Try uncommenting this if you see things break -- YMMV. + # NO_MMAP = YesPlease NO_IPV6 = YesPlease X = .exe ALL_CFLAGS += -DUSE_SYMLINK_HEAD=0 diff --git a/date.c b/date.c index d2a67ccf07..3e11500eda 100644 --- a/date.c +++ b/date.c @@ -468,12 +468,52 @@ static void update_tm(struct tm *tm, unsigned long sec) localtime_r(&n, tm); } +static void date_yesterday(struct tm *tm, int *num) +{ + update_tm(tm, 24*60*60); +} + +static void date_time(struct tm *tm, int hour) +{ + if (tm->tm_hour < hour) + date_yesterday(tm, NULL); + tm->tm_hour = hour; + tm->tm_min = 0; + tm->tm_sec = 0; +} + +static void date_midnight(struct tm *tm, int *num) +{ + date_time(tm, 0); +} + +static void date_noon(struct tm *tm, int *num) +{ + date_time(tm, 12); +} + +static void date_tea(struct tm *tm, int *num) +{ + date_time(tm, 17); +} + +static const struct special { + const char *name; + void (*fn)(struct tm *, int *); +} special[] = { + { "yesterday", date_yesterday }, + { "noon", date_noon }, + { "midnight", date_midnight }, + { "tea", date_tea }, + { NULL } +}; + static const char *number_name[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", }; -static struct typelen { +static const struct typelen { const char *type; int length; } typelen[] = { @@ -487,7 +527,8 @@ static struct typelen { static const char *approxidate_alpha(const char *date, struct tm *tm, int *num) { - struct typelen *tl; + const struct typelen *tl; + const struct special *s; const char *end = date; int n = 1, i; @@ -502,9 +543,12 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, int *num) } } - if (match_string(date, "yesterday") > 8) { - update_tm(tm, 24*60*60); - return end; + for (s = special; s->name; s++) { + int len = strlen(s->name); + if (match_string(date, s->name) == len) { + s->fn(tm, num); + return end; + } } if (!*num) { diff --git a/git-branch.sh b/git-branch.sh index 11d52fd78e..2594518e9f 100755 --- a/git-branch.sh +++ b/git-branch.sh @@ -3,7 +3,7 @@ . git-sh-setup || die "Not a git archive" usage () { - echo >&2 "usage: $(basename $0)"' [-d ] | [ [start-point]] + echo >&2 "usage: $(basename $0)"' [-d ] | [[-f] [start-point]] If no arguments, show available branches and mark current branch with a star. If one argument, create a new branch based off of current HEAD. @@ -12,11 +12,12 @@ If two arguments, create a new branch based off of . exit 1 } +headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD | + sed -e 's|^refs/heads/||') + delete_branch () { option="$1" shift - headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD | - sed -e 's|^refs/heads/||') for branch_name do case ",$headref," in @@ -52,6 +53,7 @@ delete_branch () { exit 0 } +force= while case "$#,$1" in 0,*) break ;; *,-*) ;; *) break ;; esac do case "$1" in @@ -59,6 +61,9 @@ do delete_branch "$@" exit ;; + -f) + force="$1" + ;; --) shift break @@ -72,8 +77,6 @@ done case "$#" in 0) - headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD | - sed -e 's|^refs/heads/||') git-rev-parse --symbolic --all | sed -ne 's|^refs/heads/||p' | sort | @@ -97,10 +100,18 @@ branchname="$1" rev=$(git-rev-parse --verify "$head") || exit -[ -e "$GIT_DIR/refs/heads/$branchname" ] && - die "$branchname already exists." git-check-ref-format "heads/$branchname" || die "we do not like '$branchname' as a branch name." +if [ -e "$GIT_DIR/refs/heads/$branchname" ] +then + if test '' = "$force" + then + die "$branchname already exists." + elif test "$branchname" = "$headref" + then + die "cannot force-update the current branch." + fi +fi git update-ref "refs/heads/$branchname" $rev diff --git a/git-fetch.sh b/git-fetch.sh index 8564cbfd7a..6586e773e6 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -12,6 +12,7 @@ IFS="$LF" tags= append= force= +verbose= update_head_ok= while case "$#" in 0) break ;; esac do @@ -30,6 +31,9 @@ do --update-head-o|--update-head-ok) update_head_ok=t ;; + -v|--verbose) + verbose=Yes + ;; *) break ;; @@ -91,12 +95,12 @@ append_fetch_head () { then headc_=$(git-rev-parse --verify "$head_^0") || exit echo "$headc_ $not_for_merge_ $note_" >>"$GIT_DIR/FETCH_HEAD" - echo >&2 "* committish: $head_" - echo >&2 " $note_" + [ "$verbose" ] && echo >&2 "* committish: $head_" + [ "$verbose" ] && echo >&2 " $note_" else echo "$head_ not-for-merge $note_" >>"$GIT_DIR/FETCH_HEAD" - echo >&2 "* non-commit: $head_" - echo >&2 " $note_" + [ "$verbose" ] && echo >&2 "* non-commit: $head_" + [ "$verbose" ] && echo >&2 " $note_" fi if test "$local_name_" != "" then @@ -116,7 +120,7 @@ fast_forward_local () { then if now_=$(cat "$GIT_DIR/$1") && test "$now_" = "$2" then - echo >&2 "* $1: same as $3" + [ "$verbose" ] && echo >&2 "* $1: same as $3" else echo >&2 "* $1: updating with $3" fi diff --git a/git-prune.sh b/git-prune.sh index aa79807313..c4de7f5f25 100755 --- a/git-prune.sh +++ b/git-prune.sh @@ -31,7 +31,7 @@ git-prune-packed $dryrun redundant=$(git-pack-redundant --all) if test "" != "$redundant" then - if test "" = $dryrun + if test "" = "$dryrun" then echo "$redundant" | xargs rm -f else diff --git a/git-rebase.sh b/git-rebase.sh index fa95009091..5289762883 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -5,65 +5,25 @@ . git-sh-setup || die "Not a git archive." -usage="usage: $0 "' [] - -Uses output from git-cherry to rebase local commits to the new head of -upstream tree.' - -case "$#,$1" in -1,*..*) - upstream=$(expr "$1" : '\(.*\)\.\.') ours=$(expr "$1" : '.*\.\.\(.*\)$') - set x "$upstream" "$ours" - shift ;; -esac +# The other head is given +other=$(git-rev-parse --verify "$1^0") || exit +# The tree must be really really clean. git-update-index --refresh || exit +diff=$(git-diff-index --cached --name-status -r HEAD) +case "$different" in +?*) echo "$diff" + exit 1 + ;; +esac +# If the branch to rebase is given, first switch to it. case "$#" in -1) ours_symbolic=HEAD ;; -2) ours_symbolic="$2" ;; -*) die "$usage" ;; +2) + git-checkout "$2" || exit esac -upstream=`git-rev-parse --verify "$1"` && -ours=`git-rev-parse --verify "$ours_symbolic"` || exit -different1=$(git-diff-index --name-only --cached "$ours") && -different2=$(git-diff-index --name-only "$ours") && -test "$different1$different2" = "" || -die "Your working tree does not match $ours_symbolic." - -git-read-tree -m -u $ours $upstream && -new_head=$(git-rev-parse --verify "$upstream^0") && -git-update-ref HEAD "$new_head" || exit - -tmp=.rebase-tmp$$ -fail=$tmp-fail -trap "rm -rf $tmp-*" 1 2 3 15 - ->$fail - -git-cherry -v $upstream $ours | -while read sign commit msg -do - case "$sign" in - -) - echo >&2 "* Already applied: $msg" - continue ;; - esac - echo >&2 "* Applying: $msg" - S=$(git-rev-parse --verify HEAD) && - git-cherry-pick --replay $commit || { - echo >&2 "* Not applying the patch and continuing." - echo $commit >>$fail - git-reset --hard $S - } -done -if test -s $fail -then - echo >&2 Some commits could not be rebased, check by hand: - cat >&2 $fail - echo >&2 "(the same list of commits are found in $tmp)" - exit 1 -else - rm -f $fail -fi +# Rewind the head to "$other" +git-reset --hard "$other" +git-format-patch -k --stdout --full-index "$other" ORIG_HEAD | +git am --binary -3 -k diff --git a/git-repack.sh b/git-repack.sh index e58fdd6d87..55a7b27dcd 100755 --- a/git-repack.sh +++ b/git-repack.sh @@ -63,9 +63,22 @@ exit if test "$remove_redundant" = t then sync - redundant=$(git-pack-redundant --all) - if test "$redundant" != "" ; then - echo $redundant | xargs rm + if test "$all_into_one" = t + then + cd "$PACKDIR" + existing=`find . -type f \( -name '*.pack' -o -name '*.idx' \) -print` + for e in $existing + do + case "$e" in + ./pack-$name.pack | ./pack-$name.idx) ;; + *) rm -f $e ;; + esac + done + else + redundant=$(git-pack-redundant --all) + if test "$redundant" != "" ; then + echo $redundant | xargs rm + fi fi fi diff --git a/git.c b/git.c index b9b8c62f47..bdd3f8d01c 100644 --- a/git.c +++ b/git.c @@ -59,7 +59,8 @@ static void add_cmdname(const char *name, int len) if (!ent) oom(); ent->len = len; - memcpy(ent->name, name, len+1); + memcpy(ent->name, name, len); + ent->name[len] = 0; cmdname[cmdname_cnt++] = ent; } @@ -132,6 +133,8 @@ static void list_commands(const char *exec_path, const char *pattern) continue; entlen = strlen(de->d_name); + if (4 < entlen && !strcmp(de->d_name + entlen - 4, ".exe")) + entlen -= 4; if (longest < entlen) longest = entlen; diff --git a/pack-redundant.c b/pack-redundant.c index 51d7341b0b..fb6cb48502 100644 --- a/pack-redundant.c +++ b/pack-redundant.c @@ -291,6 +291,7 @@ struct pll * get_all_permutations(struct pack_list *list) hint[0] = new_pll; new_pll->next = NULL; new_pll->pl = list; + new_pll->pl_size = 1; return new_pll; } @@ -439,7 +440,7 @@ void minimize(struct pack_list **min) break; /* ignore all larger permutations */ if (is_superset(perm->pl, missing)) { new_perm = xmalloc(sizeof(struct pll)); - new_perm->pl = perm->pl; + memcpy(new_perm, perm, sizeof(struct pll)); new_perm->next = perm_ok; perm_ok = new_perm; } @@ -496,7 +497,7 @@ void load_all_objects() } /* this scales like O(n^2) */ -void cmp_packs() +void cmp_local_packs() { struct pack_list *subset, *pl = local_packs; @@ -505,16 +506,21 @@ void cmp_packs() cmp_two_packs(pl, subset); pl = pl->next; } +} - pl = altodb_packs; - while (pl) { - subset = local_packs; - while (subset) { - llist_sorted_difference_inplace(subset->unique_objects, - pl->all_objects); - subset = subset->next; +void scan_alt_odb_packs() +{ + struct pack_list *local, *alt; + + alt = altodb_packs; + while (alt) { + local = local_packs; + while (local) { + llist_sorted_difference_inplace(local->unique_objects, + alt->all_objects); + local = local->next; } - pl = pl->next; + alt = alt->next; } } @@ -524,6 +530,9 @@ struct pack_list * add_pack(struct packed_git *p) size_t off; void *base; + if (!p->pack_local && !(alt_odb || verbose)) + return NULL; + l.pack = p; llist_init(&l.all_objects); @@ -531,14 +540,14 @@ struct pack_list * add_pack(struct packed_git *p) base = (void *)p->index_base; while (off <= p->index_size - 3 * 20) { llist_insert_back(l.all_objects, base + off); - off+=24; + off += 24; } /* this list will be pruned in cmp_two_packs later */ l.unique_objects = llist_copy(l.all_objects); if (p->pack_local) return pack_list_insert(&local_packs, &l); else - return alt_odb ? pack_list_insert(&altodb_packs, &l) : NULL; + return pack_list_insert(&altodb_packs, &l); } struct pack_list * add_pack_file(char *filename) @@ -606,11 +615,14 @@ int main(int argc, char **argv) if (local_packs == NULL) die("Zero packs found!\n"); - cmp_packs(); - load_all_objects(); + cmp_local_packs(); + if (alt_odb) + scan_alt_odb_packs(); + minimize(&min); + if (verbose) { fprintf(stderr, "There are %lu packs available in alt-odbs.\n", (unsigned long)pack_list_size(altodb_packs));