Browse Source

Merge branch 'master'

* master:
  Add howto about separating topics.
  Merge branch 'pb/repo'
  Add support for explicit type specifiers when calling git-repo-config
  Merge branch 'jc/fixdiff'
  diff-tree: do not default to -c
  Avoid using "git-var -l" until it gets fixed.
  t5500: adjust to change in pack-object reporting behaviour.
  Only call git-rerere if $GIT_DIR/rr-cache exists.
  Use a relative path for SVN importing
  fetch-clone progress: finishing touches.
  Fix fetch-clone in the presense of signals
  Make "git clone" pack-fetching download statistics better
  Make "git clone" less of a deathly quiet experience
maint
Junio C Hamano 19 years ago
parent
commit
cfac3f3fa7
  1. 18
      Documentation/git-repo-config.txt
  2. 91
      Documentation/howto/separating-topic-branches.txt
  3. 2
      cache.h
  4. 10
      clone-pack.c
  5. 4
      diff-tree.c
  6. 77
      fetch-clone.c
  7. 2
      fetch-pack.c
  8. 5
      git-am.sh
  9. 5
      git-commit.sh
  10. 5
      git-merge.sh
  11. 8
      git-pull.sh
  12. 6
      git-sh-setup.sh
  13. 2
      git-svnimport.perl
  14. 2
      git-whatchanged.sh
  15. 43
      pack-objects.c
  16. 27
      repo-config.c
  17. 2
      t/t5500-fetch-pack.sh

18
Documentation/git-repo-config.txt

@ -8,12 +8,12 @@ git-repo-config - Get and set options in .git/config. @@ -8,12 +8,12 @@ git-repo-config - Get and set options in .git/config.

SYNOPSIS
--------
'git-repo-config' name [value [value_regex]]
'git-repo-config' --replace-all name [value [value_regex]]
'git-repo-config' --get name [value_regex]
'git-repo-config' --get-all name [value_regex]
'git-repo-config' --unset name [value_regex]
'git-repo-config' --unset-all name [value_regex]
'git-repo-config' [type] name [value [value_regex]]
'git-repo-config' [type] --replace-all name [value [value_regex]]
'git-repo-config' [type] --get name [value_regex]
'git-repo-config' [type] --get-all name [value_regex]
'git-repo-config' [type] --unset name [value_regex]
'git-repo-config' [type] --unset-all name [value_regex]

DESCRIPTION
-----------
@ -26,6 +26,12 @@ should provide a POSIX regex for the value. If you want to handle the lines @@ -26,6 +26,12 @@ should provide a POSIX regex for the value. If you want to handle the lines
*not* matching the regex, just prepend a single exclamation mark in front
(see EXAMPLES).

The type specifier can be either '--int' or '--bool', which will make
'git-repo-config' ensure that the variable(s) are of the given type and
convert the value to the canonical form (simple decimal number for int,
a "true" or "false" string for bool). If no type specifier is passed,
no checks or transformations are performed on the value.

This command will fail if

. .git/config is invalid,

91
Documentation/howto/separating-topic-branches.txt

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
From: Junio C Hamano <junkio@cox.net>
Subject: Separating topic branches
Abstract: In this article, JC describes how to separate topic branches.

This text was originally a footnote to a discussion about the
behaviour of the git diff commands.

Often I find myself doing that [running diff against something other
than HEAD] while rewriting messy development history. For example, I
start doing some work without knowing exactly where it leads, and end
up with a history like this:

"master"
o---o
\ "topic"
o---o---o---o---o---o

At this point, "topic" contains something I know I want, but it
contains two concepts that turned out to be completely independent.
And often, one topic component is larger than the other. It may
contain more than two topics.

In order to rewrite this mess to be more manageable, I would first do
"diff master..topic", to extract the changes into a single patch, start
picking pieces from it to get logically self-contained units, and
start building on top of "master":

$ git diff master..topic >P.diff
$ git checkout -b topicA master
... pick and apply pieces from P.diff to build
... commits on topicA branch.
o---o---o
/ "topicA"
o---o"master"
\ "topic"
o---o---o---o---o---o

Before doing each commit on "topicA" HEAD, I run "diff HEAD"
before update-index the affected paths, or "diff --cached HEAD"
after. Also I would run "diff --cached master" to make sure
that the changes are only the ones related to "topicA". Usually
I do this for smaller topics first.

After that, I'd do the remainder of the original "topic", but
for that, I do not start from the patchfile I extracted by
comparing "master" and "topic" I used initially. Still on
"topicA", I extract "diff topic", and use it to rebuild the
other topic:

$ git diff -R topic >P.diff ;# --cached also would work fine
$ git checkout -b topicB master
... pick and apply pieces from P.diff to build
... commits on topicB branch.

"topicB"
o---o---o---o---o
/
/o---o---o
|/ "topicA"
o---o"master"
\ "topic"
o---o---o---o---o---o

After I am done, I'd try a pretend-merge between "topicA" and
"topicB" in order to make sure I have not missed anything:

$ git pull . topicA ;# merge it into current "topicB"
$ git diff topic
"topicB"
o---o---o---o---o---* (pretend merge)
/ /
/o---o---o----------'
|/ "topicA"
o---o"master"
\ "topic"
o---o---o---o---o---o

The last diff better not to show anything other than cleanups
for crufts. Then I can finally clean things up:

$ git branch -D topic
$ git reset --hard HEAD^ ;# nuke pretend merge

"topicB"
o---o---o---o---o
/
/o---o---o
|/ "topicA"
o---o"master"

2
cache.h

@ -350,6 +350,6 @@ extern int copy_fd(int ifd, int ofd); @@ -350,6 +350,6 @@ extern int copy_fd(int ifd, int ofd);

/* Finish off pack transfer receiving end */
extern int receive_unpack_pack(int fd[2], const char *me, int quiet);
extern int receive_keep_pack(int fd[2], const char *me);
extern int receive_keep_pack(int fd[2], const char *me, int quiet);

#endif /* CACHE_H */

10
clone-pack.c

@ -6,6 +6,8 @@ static const char clone_pack_usage[] = @@ -6,6 +6,8 @@ static const char clone_pack_usage[] =
"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
static const char *exec = "git-upload-pack";

static int quiet = 0;

static void clone_handshake(int fd[2], struct ref *ref)
{
unsigned char sha1[20];
@ -123,7 +125,9 @@ static int clone_pack(int fd[2], int nr_match, char **match) @@ -123,7 +125,9 @@ static int clone_pack(int fd[2], int nr_match, char **match)
}
clone_handshake(fd, refs);

status = receive_keep_pack(fd, "git-clone-pack");
status = receive_keep_pack(fd, "git-clone-pack", quiet);
if (!quiet)
fprintf(stderr, "\n");

if (!status) {
if (nr_match == 0)
@ -154,8 +158,10 @@ int main(int argc, char **argv) @@ -154,8 +158,10 @@ int main(int argc, char **argv)
char *arg = argv[i];

if (*arg == '-') {
if (!strcmp("-q", arg))
if (!strcmp("-q", arg)) {
quiet = 1;
continue;
}
if (!strncmp("--exec=", arg, 7)) {
exec = arg + 7;
continue;

4
diff-tree.c

@ -6,7 +6,7 @@ static int show_root_diff = 0; @@ -6,7 +6,7 @@ static int show_root_diff = 0;
static int no_commit_id = 0;
static int verbose_header = 0;
static int ignore_merges = 1;
static int combine_merges = 1;
static int combine_merges = 0;
static int dense_combined_merges = 0;
static int read_stdin = 0;
static int always_show_header = 0;
@ -248,7 +248,7 @@ int main(int argc, const char **argv) @@ -248,7 +248,7 @@ int main(int argc, const char **argv)
continue;
}
if (!strcmp(arg, "-m")) {
combine_merges = ignore_merges = 0;
ignore_merges = 0;
continue;
}
if (!strcmp(arg, "-c")) {

77
fetch-clone.c

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
#include "cache.h"
#include "exec_cmd.h"
#include <sys/wait.h>
#include <sys/time.h>

static int finish_pack(const char *pack_tmp_name, const char *me)
{
@ -129,10 +130,35 @@ int receive_unpack_pack(int fd[2], const char *me, int quiet) @@ -129,10 +130,35 @@ int receive_unpack_pack(int fd[2], const char *me, int quiet)
die("git-unpack-objects died of unnatural causes %d", status);
}

int receive_keep_pack(int fd[2], const char *me)
/*
* We average out the download speed over this many "events", where
* an event is a minimum of about half a second. That way, we get
* a reasonably stable number.
*/
#define NR_AVERAGE (4)

/*
* A "binary msec" is a power-of-two-msec, aka 1/1024th of a second.
* Keeing the time in that format means that "bytes / msecs" means
* is the same as kB/s (modulo rounding).
*
* 1000512 is a magic number (usecs in a second, rounded up by half
* of 1024, to make "rounding" come out right ;)
*/
#define usec_to_binarymsec(x) ((int)(x) / (1000512 >> 10))

int receive_keep_pack(int fd[2], const char *me, int quiet)
{
char tmpfile[PATH_MAX];
int ofd, ifd;
unsigned long total;
static struct timeval prev_tv;
struct average {
unsigned long bytes;
unsigned long time;
} download[NR_AVERAGE] = { {0, 0}, };
unsigned long avg_bytes, avg_time;
int idx = 0;

ifd = fd[0];
snprintf(tmpfile, sizeof(tmpfile),
@ -141,6 +167,10 @@ int receive_keep_pack(int fd[2], const char *me) @@ -141,6 +167,10 @@ int receive_keep_pack(int fd[2], const char *me)
if (ofd < 0)
return error("unable to create temporary file %s", tmpfile);

gettimeofday(&prev_tv, NULL);
total = 0;
avg_bytes = 0;
avg_time = 0;
while (1) {
char buf[8192];
ssize_t sz, wsz, pos;
@ -148,10 +178,13 @@ int receive_keep_pack(int fd[2], const char *me) @@ -148,10 +178,13 @@ int receive_keep_pack(int fd[2], const char *me)
if (sz == 0)
break;
if (sz < 0) {
error("error reading pack (%s)", strerror(errno));
close(ofd);
unlink(tmpfile);
return -1;
if (errno != EINTR && errno != EAGAIN) {
error("error reading pack (%s)", strerror(errno));
close(ofd);
unlink(tmpfile);
return -1;
}
sz = 0;
}
pos = 0;
while (pos < sz) {
@ -165,6 +198,40 @@ int receive_keep_pack(int fd[2], const char *me) @@ -165,6 +198,40 @@ int receive_keep_pack(int fd[2], const char *me)
}
pos += wsz;
}
total += sz;
if (!quiet) {
static unsigned long last;
struct timeval tv;
unsigned long diff = total - last;
/* not really "msecs", but a power-of-two millisec (1/1024th of a sec) */
unsigned long msecs;

gettimeofday(&tv, NULL);
msecs = tv.tv_sec - prev_tv.tv_sec;
msecs <<= 10;
msecs += usec_to_binarymsec(tv.tv_usec - prev_tv.tv_usec);

if (msecs > 500) {
prev_tv = tv;
last = total;

/* Update averages ..*/
avg_bytes += diff;
avg_time += msecs;
avg_bytes -= download[idx].bytes;
avg_time -= download[idx].time;
download[idx].bytes = diff;
download[idx].time = msecs;
idx++;
if (idx >= NR_AVERAGE)
idx = 0;

fprintf(stderr, "%4lu.%03luMB (%lu kB/s) \r",
total >> 20,
1000*((total >> 10) & 1023)>>10,
avg_bytes / avg_time );
}
}
}
close(ofd);
return finish_pack(tmpfile, me);

2
fetch-pack.c

@ -378,7 +378,7 @@ static int fetch_pack(int fd[2], int nr_match, char **match) @@ -378,7 +378,7 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
fprintf(stderr, "warning: no common commits\n");

if (keep_pack)
status = receive_keep_pack(fd, "git-fetch-pack");
status = receive_keep_pack(fd, "git-fetch-pack", quiet);
else
status = receive_unpack_pack(fd, "git-fetch-pack", quiet);


5
git-am.sh

@ -88,7 +88,10 @@ fall_back_3way () { @@ -88,7 +88,10 @@ fall_back_3way () {
# saying that we reverted all those changes.

git-merge-resolve $orig_tree -- HEAD $his_tree || {
git-rerere
if test -d "$GIT_DIR/rr-cache"
then
git-rerere
fi
echo Failed to merge in the changes.
exit 1
}

5
git-commit.sh

@ -638,7 +638,10 @@ else @@ -638,7 +638,10 @@ else
fi
ret="$?"
rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG"
git-rerere
if test -d "$GIT_DIR/rr-cache"
then
git-rerere
fi

if test -x "$GIT_DIR"/hooks/post-commit && test "$ret" = 0
then

5
git-merge.sh

@ -309,6 +309,9 @@ Conflicts: @@ -309,6 +309,9 @@ Conflicts:
sed -e 's/^[^ ]* / /' |
uniq
} >>"$GIT_DIR/MERGE_MSG"
git rerere
if test -d "$GIT_DIR/rr-cache"
then
git-rerere
fi
die "Automatic merge failed; fix up by hand"
fi

8
git-pull.sh

@ -70,21 +70,21 @@ case "$merge_head" in @@ -70,21 +70,21 @@ case "$merge_head" in
exit 0
;;
?*' '?*)
var=`git-var -l | sed -ne 's/^pull\.octopus=/-s /p'`
var=`git repo-config --get pull.octopus`
if test '' = "$var"
then
strategy_default_args='-s octopus'
else
strategy_default_args=$var
strategy_default_args="-s $var"
fi
;;
*)
var=`git-var -l | sed -ne 's/^pull\.twohead=/-s /p'`
var=`git repo-config --get pull.twohead`
if test '' = "$var"
then
strategy_default_args='-s recursive'
else
strategy_default_args=$var
strategy_default_args="-s $var"
fi
;;
esac

6
git-sh-setup.sh

@ -41,7 +41,11 @@ then @@ -41,7 +41,11 @@ then
: ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}

# Make sure we are in a valid repository of a vintage we understand.
GIT_DIR="$GIT_DIR" git-var GIT_AUTHOR_IDENT >/dev/null || exit
GIT_DIR="$GIT_DIR" git repo-config --get core.nosuch >/dev/null
if test $? == 128
then
exit
fi
else
GIT_DIR=$(git-rev-parse --git-dir) || exit
fi

2
git-svnimport.perl

@ -318,7 +318,7 @@ sub get_file($$$) { @@ -318,7 +318,7 @@ sub get_file($$$) {
die $res->status_line." at $url\n";
}
} else {
$name = $svn->file("/$svnpath",$rev);
$name = $svn->file("$svnpath",$rev);
return undef unless defined $name;
}


2
git-whatchanged.sh

@ -10,7 +10,7 @@ case "$0" in @@ -10,7 +10,7 @@ case "$0" in
count=
test -z "$diff_tree_flags" &&
diff_tree_flags=$(git-repo-config --get whatchanged.difftree)
diff_tree_default_flags='-M --abbrev' ;;
diff_tree_default_flags='-c -M --abbrev' ;;
*show)
count=-n1
test -z "$diff_tree_flags" &&

43
pack-objects.c

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
#include "delta.h"
#include "pack.h"
#include "csum-file.h"
#include <sys/time.h>

static const char pack_usage[] = "git-pack-objects [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list";

@ -26,6 +27,7 @@ static struct object_entry *objects = NULL; @@ -26,6 +27,7 @@ static struct object_entry *objects = NULL;
static int nr_objects = 0, nr_alloc = 0;
static const char *base_name;
static unsigned char pack_file_sha1[20];
static int progress = 0;

static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)
{
@ -362,10 +364,13 @@ static void find_deltas(struct object_entry **list, int window, int depth) @@ -362,10 +364,13 @@ static void find_deltas(struct object_entry **list, int window, int depth)
int i, idx;
unsigned int array_size = window * sizeof(struct unpacked);
struct unpacked *array = xmalloc(array_size);
int eye_candy;

memset(array, 0, array_size);
i = nr_objects;
idx = 0;
eye_candy = i - (nr_objects / 20);

while (--i >= 0) {
struct object_entry *entry = list[i];
struct unpacked *n = array + idx;
@ -373,6 +378,10 @@ static void find_deltas(struct object_entry **list, int window, int depth) @@ -373,6 +378,10 @@ static void find_deltas(struct object_entry **list, int window, int depth)
char type[10];
int j;

if (progress && i <= eye_candy) {
eye_candy -= nr_objects / 20;
fputc('.', stderr);
}
free(n->data);
n->entry = entry;
n->data = read_sha1_file(entry->sha1, type, &size);
@ -404,11 +413,13 @@ static void prepare_pack(int window, int depth) @@ -404,11 +413,13 @@ static void prepare_pack(int window, int depth)
{
get_object_details();

fprintf(stderr, "Packing %d objects\n", nr_objects);

if (progress)
fprintf(stderr, "Packing %d objects", nr_objects);
sorted_by_type = create_sorted_list(type_size_sort);
if (window && depth)
find_deltas(sorted_by_type, window+1, depth);
if (progress)
fputc('\n', stderr);
write_pack_file();
}

@ -472,6 +483,10 @@ int main(int argc, char **argv) @@ -472,6 +483,10 @@ int main(int argc, char **argv)
int window = 10, depth = 10, pack_to_stdout = 0;
struct object_entry **list;
int i;
struct timeval prev_tv;
int eye_candy = 0;
int eye_candy_incr = 500;


setup_git_directory();

@ -519,12 +534,34 @@ int main(int argc, char **argv) @@ -519,12 +534,34 @@ int main(int argc, char **argv)
if (pack_to_stdout != !base_name)
usage(pack_usage);

progress = isatty(2);

prepare_packed_git();
if (progress) {
fprintf(stderr, "Generating pack...\n");
gettimeofday(&prev_tv, NULL);
}
while (fgets(line, sizeof(line), stdin) != NULL) {
unsigned int hash;
char *p;
unsigned char sha1[20];

if (progress && (eye_candy <= nr_objects)) {
fprintf(stderr, "Counting objects...%d\r", nr_objects);
if (eye_candy && (50 <= eye_candy_incr)) {
struct timeval tv;
int time_diff;
gettimeofday(&tv, NULL);
time_diff = (tv.tv_sec - prev_tv.tv_sec);
time_diff <<= 10;
time_diff += (tv.tv_usec - prev_tv.tv_usec);
if ((1 << 9) < time_diff)
eye_candy_incr += 50;
else if (50 < eye_candy_incr)
eye_candy_incr -= 50;
}
eye_candy += eye_candy_incr;
}
if (get_sha1_hex(line, sha1))
die("expected sha1, got garbage:\n %s", line);
hash = 0;
@ -537,6 +574,8 @@ int main(int argc, char **argv) @@ -537,6 +574,8 @@ int main(int argc, char **argv)
}
add_object_entry(sha1, hash);
}
if (progress)
fprintf(stderr, "Done counting %d objects.\n", nr_objects);
if (non_empty && !nr_objects)
return 0;


27
repo-config.c

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
#include <regex.h>

static const char git_config_set_usage[] =
"git-repo-config [--get | --get-all | --replace-all | --unset | --unset-all] name [value [value_regex]]";
"git-repo-config [ --bool | --int ] [--get | --get-all | --replace-all | --unset | --unset-all] name [value [value_regex]]";

static char* key = NULL;
static char* value = NULL;
@ -10,6 +10,7 @@ static regex_t* regexp = NULL; @@ -10,6 +10,7 @@ static regex_t* regexp = NULL;
static int do_all = 0;
static int do_not_match = 0;
static int seen = 0;
static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;

static int show_config(const char* key_, const char* value_)
{
@ -25,7 +26,17 @@ static int show_config(const char* key_, const char* value_) @@ -25,7 +26,17 @@ static int show_config(const char* key_, const char* value_)
fprintf(stderr, "More than one value: %s\n", value);
free(value);
}
value = strdup(value_);

if (type == T_INT) {
value = malloc(256);
sprintf(value, "%d", git_config_int(key_, value_));
} else if (type == T_BOOL) {
value = malloc(256);
sprintf(value, "%s", git_config_bool(key_, value_)
? "true" : "false");
} else {
value = strdup(value_ ? value_ : "");
}
seen++;
}
return 0;
@ -73,6 +84,18 @@ static int get_value(const char* key_, const char* regex_) @@ -73,6 +84,18 @@ static int get_value(const char* key_, const char* regex_)
int main(int argc, const char **argv)
{
setup_git_directory();

while (1 < argc) {
if (!strcmp(argv[1], "--int"))
type = T_INT;
else if (!strcmp(argv[1], "--bool"))
type = T_BOOL;
else
break;
argc--;
argv++;
}

switch (argc) {
case 2:
return get_value(argv[1], NULL);

2
t/t5500-fetch-pack.sh

@ -76,7 +76,7 @@ function pull_to_client () { @@ -76,7 +76,7 @@ function pull_to_client () {
git-symbolic-ref HEAD refs/heads/${heads:0:1}
test_expect_success "fsck" 'git-fsck-objects --full > fsck.txt 2>&1'
test_expect_object_count "after $number pull" $count
pack_count=$(grep Packing log.txt|tr -dc "0-9")
pack_count=$(grep Unpacking log.txt|tr -dc "0-9")
test -z "$pack_count" && pack_count=0
if [ -z "$no_strict_count_check" ]; then
test_expect_success "minimal count" "test $count = $pack_count"

Loading…
Cancel
Save