summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <junio@hera.kernel.org>2005-10-20 17:06:15 -0700
committerJunio C Hamano <junio@hera.kernel.org>2005-10-20 17:06:15 -0700
commitbfadbeddd1b54af8ab08a6c556c43c756ec85588 (patch)
tree50f9bed9a78e1f51178ebf6be3cd9c20b2ffcb0b
parentea5a65a59916503d2a14369c46b1023384d51645 (diff)
parent6e1c6c103c522d01829f3a63992a023ff031e851 (diff)
downloadgit-bfadbeddd1b54af8ab08a6c556c43c756ec85588.tar.gz
Merge /pub/scm/git/git to recover lost side branch
Sorry for the mistake of rewinding something already pushed out. This recovers the side branch lost by that mistake, specifically ea5a65a59916503d2a14369c46b1023384d51645 commit. Signed-off-by: Junio C Hamano <junio@hera.kernel.org>
-rw-r--r--Documentation/git-clone-pack.txt15
-rw-r--r--Documentation/git-fetch.txt5
-rw-r--r--Documentation/git-pull.txt4
-rw-r--r--Documentation/git-push.txt9
-rw-r--r--Documentation/pull-fetch-param.txt10
-rw-r--r--clone-pack.c72
-rw-r--r--daemon.c21
-rw-r--r--fetch-pack.c57
-rwxr-xr-xgit-count-objects.sh2
-rw-r--r--http-fetch.c29
-rw-r--r--sha1_name.c4
-rw-r--r--upload-pack.c45
12 files changed, 164 insertions, 109 deletions
diff --git a/Documentation/git-clone-pack.txt b/Documentation/git-clone-pack.txt
index b58165a5fc..cfc7b62f31 100644
--- a/Documentation/git-clone-pack.txt
+++ b/Documentation/git-clone-pack.txt
@@ -8,26 +8,17 @@ git-clone-pack - Clones a repository by receiving packed objects.
SYNOPSIS
--------
-'git-clone-pack' [-q] [--keep] [--exec=<git-upload-pack>] [<host>:]<directory> [<head>...]
+'git-clone-pack' [--exec=<git-upload-pack>] [<host>:]<directory> [<head>...]
DESCRIPTION
-----------
Clones a repository into the current repository by invoking
'git-upload-pack', possibly on the remote host via ssh, in
-the named repository, and invoking 'git-unpack-objects' locally
-to receive the pack.
+the named repository, and stores the sent pack in the local
+repository.
OPTIONS
-------
--q::
- Pass '-q' flag to 'git-unpack-objects'; this makes the
- cloning process less verbose.
-
---keep::
- Do not invoke 'git-unpack-objects' on received data, but
- create a single packfile out of it instead, and store it
- in the object database.
-
--exec=<git-upload-pack>::
Use this to specify the path to 'git-upload-pack' on the
remote side, if it is not found on your $PATH.
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index c0b5aac5f2..71693650c4 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -25,6 +25,11 @@ OPTIONS
-------
include::pull-fetch-param.txt[]
+-a, \--append::
+ Append ref names and object names of fetched refs to the
+ existing contents of $GIT_DIR/FETCH_HEAD. Without this
+ option old data in $GIT_DIR/FETCH_HEAD will be overwritten.
+
-u, \--update-head-ok::
By default 'git-fetch' refuses to update the head which
corresponds to the current branch. This flag disables the
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index 952779292b..bae05dee99 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -24,6 +24,10 @@ OPTIONS
-------
include::pull-fetch-param.txt[]
+-a, \--append::
+ Append ref names and object names of fetched refs to the
+ existing contents of $GIT_DIR/FETCH_HEAD. Without this
+ option old data in $GIT_DIR/FETCH_HEAD will be overwritten.
Author
------
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 809ac8ba06..f45ac5ee49 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -21,6 +21,15 @@ OPTIONS
-------
include::pull-fetch-param.txt[]
+\--all::
+ Instead of naming each ref to push, specifies all refs
+ to be pushed.
+
+-f, \--force::
+ Usually, the command refuses to update a local ref that is
+ not an ancestor of the remote ref used to overwrite it.
+ This flag disables the check. What this means is that the
+ local repository can lose commits; use it with care.
Author
------
diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt
index 51222b6f3f..e8db9d7ca5 100644
--- a/Documentation/pull-fetch-param.txt
+++ b/Documentation/pull-fetch-param.txt
@@ -75,13 +75,3 @@ Some short-cut notations are also supported.
pushing. That is, do not store it locally if
fetching, and update the same name if pushing.
--a, \--append::
- Append ref names and object names of fetched refs to the
- existing contents of $GIT_DIR/FETCH_HEAD. Without this
- option old data in $GIT_DIR/FETCH_HEAD will be overwritten.
-
--f, \--force::
- Usually, the command refuses to update a local ref that is
- not an ancestor of the remote ref used to overwrite it.
- This flag disables the check. What this means is that the
- local repository can lose commits; use it with care.
diff --git a/clone-pack.c b/clone-pack.c
index f9b263a441..4f4975b4ab 100644
--- a/clone-pack.c
+++ b/clone-pack.c
@@ -3,10 +3,8 @@
#include "pkt-line.h"
#include <sys/wait.h>
-static int quiet;
-static int keep_pack;
static const char clone_pack_usage[] =
-"git-clone-pack [-q] [--keep] [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
+"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
static const char *exec = "git-upload-pack";
static void clone_handshake(int fd[2], struct ref *ref)
@@ -114,41 +112,6 @@ static void write_refs(struct ref *ref)
free(head_path);
}
-static int clone_by_unpack(int fd[2])
-{
- int status;
- pid_t pid;
-
- pid = fork();
- if (pid < 0)
- die("git-clone-pack: unable to fork off git-unpack-objects");
- if (!pid) {
- dup2(fd[0], 0);
- close(fd[0]);
- close(fd[1]);
- execlp("git-unpack-objects", "git-unpack-objects",
- quiet ? "-q" : NULL, NULL);
- die("git-unpack-objects exec failed");
- }
- close(fd[0]);
- close(fd[1]);
- while (waitpid(pid, &status, 0) < 0) {
- if (errno != EINTR)
- die("waiting for git-unpack-objects: %s", strerror(errno));
- }
- if (WIFEXITED(status)) {
- int code = WEXITSTATUS(status);
- if (code)
- die("git-unpack-objects died with error code %d", code);
- return 0;
- }
- if (WIFSIGNALED(status)) {
- int sig = WTERMSIG(status);
- die("git-unpack-objects died of signal %d", sig);
- }
- die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
-}
-
static int finish_pack(const char *pack_tmp_name)
{
int pipe_fd[2];
@@ -294,35 +257,13 @@ static int clone_pack(int fd[2], int nr_match, char **match)
}
clone_handshake(fd, refs);
- if (keep_pack)
- status = clone_without_unpack(fd);
- else
- status = clone_by_unpack(fd);
+ status = clone_without_unpack(fd);
if (!status)
write_refs(refs);
return status;
}
-static int clone_options(const char *var, const char *value)
-{
- if (!strcmp("clone.keeppack", var)) {
- keep_pack = git_config_bool(var, value);
- return 0;
- }
- if (!strcmp("clone.quiet", var)) {
- quiet = git_config_bool(var, value);
- return 0;
- }
- /*
- * Put other local option parsing for this program
- * here ...
- */
-
- /* Fall back on the default ones */
- return git_default_config(var, value);
-}
-
int main(int argc, char **argv)
{
int i, ret, nr_heads;
@@ -330,25 +271,20 @@ int main(int argc, char **argv)
int fd[2];
pid_t pid;
- git_config(clone_options);
nr_heads = 0;
heads = NULL;
for (i = 1; i < argc; i++) {
char *arg = argv[i];
if (*arg == '-') {
- if (!strcmp("-q", arg)) {
- quiet = 1;
+ if (!strcmp("-q", arg))
continue;
- }
if (!strncmp("--exec=", arg, 7)) {
exec = arg + 7;
continue;
}
- if (!strcmp("--keep", arg)) {
- keep_pack = 1;
+ if (!strcmp("--keep", arg))
continue;
- }
usage(clone_pack_usage);
}
dest = arg;
diff --git a/daemon.c b/daemon.c
index 9ea6c31cd1..c3381b344c 100644
--- a/daemon.c
+++ b/daemon.c
@@ -13,7 +13,9 @@
static int log_syslog;
static int verbose;
-static const char daemon_usage[] = "git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all] [directory...]";
+static const char daemon_usage[] =
+"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
+" [--timeout=n] [--init-timeout=n] [directory...]";
/* List of acceptable pathname prefixes */
static char **ok_paths = NULL;
@@ -21,6 +23,9 @@ static char **ok_paths = NULL;
/* If this is set, git-daemon-export-ok is not required */
static int export_all_trees = 0;
+/* Timeout, and initial timeout */
+static unsigned int timeout = 0;
+static unsigned int init_timeout = 0;
static void logreport(int priority, const char *err, va_list params)
{
@@ -170,6 +175,8 @@ static int upload(char *dir)
/* Enough for the longest path above including final null */
int buflen = strlen(dir)+10;
char *dirbuf = xmalloc(buflen);
+ /* Timeout as string */
+ char timeout_buf[64];
loginfo("Request for '%s'", dir);
@@ -190,8 +197,10 @@ static int upload(char *dir)
*/
signal(SIGTERM, SIG_IGN);
+ snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
+
/* git-upload-pack only ever reads stuff, so this is safe */
- execlp("git-upload-pack", "git-upload-pack", ".", NULL);
+ execlp("git-upload-pack", "git-upload-pack", "--strict", timeout_buf, ".", NULL);
return -1;
}
@@ -200,7 +209,9 @@ static int execute(void)
static char line[1000];
int len;
+ alarm(init_timeout ? init_timeout : timeout);
len = packet_read_line(0, line, sizeof(line));
+ alarm(0);
if (len && line[len-1] == '\n')
line[--len] = 0;
@@ -598,6 +609,12 @@ int main(int argc, char **argv)
export_all_trees = 1;
continue;
}
+ if (!strncmp(arg, "--timeout=", 10)) {
+ timeout = atoi(arg+10);
+ }
+ if (!strncmp(arg, "--init-timeout=", 10)) {
+ init_timeout = atoi(arg+15);
+ }
if (!strcmp(arg, "--")) {
ok_paths = &argv[i+1];
break;
diff --git a/fetch-pack.c b/fetch-pack.c
index 969e72a781..8566ab1744 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -12,31 +12,66 @@ static const char fetch_pack_usage[] =
"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
static const char *exec = "git-upload-pack";
+#define COMPLETE (1U << 0)
+
static int find_common(int fd[2], unsigned char *result_sha1,
struct ref *refs)
{
int fetching;
static char line[1000];
- int count = 0, flushes = 0, retval;
+ static char rev_command[1024];
+ int count = 0, flushes = 0, retval, rev_command_len;
FILE *revs;
- revs = popen("git-rev-list $(git-rev-parse --all)", "r");
- if (!revs)
- die("unable to run 'git-rev-list'");
-
+ strcpy(rev_command, "git-rev-list $(git-rev-parse --all)");
+ rev_command_len = strlen(rev_command);
fetching = 0;
for ( ; refs ; refs = refs->next) {
unsigned char *remote = refs->old_sha1;
- unsigned char *local = refs->new_sha1;
+ struct object *o;
- if (!memcmp(remote, local, 20))
+ /*
+ * If that object is complete (i.e. it is an ancestor of a
+ * local ref), we tell them we have it but do not have to
+ * tell them about its ancestors, which they already know
+ * about.
+ *
+ * We use lookup_object here because we are only
+ * interested in the case we *know* the object is
+ * reachable and we have already scanned it.
+ */
+ if (((o = lookup_object(remote)) != NULL) &&
+ (o->flags & COMPLETE)) {
+ struct commit_list *p;
+ struct commit *commit =
+ (struct commit *) (o = deref_tag(o));
+ if (!o)
+ goto repair;
+ if (o->type != commit_type)
+ continue;
+ p = commit->parents;
+ while (p &&
+ rev_command_len + 44 < sizeof(rev_command)) {
+ snprintf(rev_command + rev_command_len, 44,
+ " ^%s",
+ sha1_to_hex(p->item->object.sha1));
+ rev_command_len += 43;
+ p = p->next;
+ }
continue;
+ }
+ repair:
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
fetching++;
}
packet_flush(fd[1]);
if (!fetching)
return 1;
+
+ revs = popen(rev_command, "r");
+ if (!revs)
+ die("unable to run 'git-rev-list'");
+
flushes = 1;
retval = -1;
while (fgets(line, sizeof(line), revs) != NULL) {
@@ -81,7 +116,6 @@ static int find_common(int fd[2], unsigned char *result_sha1,
return retval;
}
-#define COMPLETE (1U << 0)
static struct commit_list *complete = NULL;
static int mark_complete(const char *path, const unsigned char *sha1)
@@ -89,10 +123,13 @@ static int mark_complete(const char *path, const unsigned char *sha1)
struct object *o = parse_object(sha1);
while (o && o->type == tag_type) {
+ struct tag *t = (struct tag *) o;
+ if (!t->tagged)
+ break; /* broken repository */
o->flags |= COMPLETE;
- o = parse_object(((struct tag *)o)->tagged->sha1);
+ o = parse_object(t->tagged->sha1);
}
- if (o->type == commit_type) {
+ if (o && o->type == commit_type) {
struct commit *commit = (struct commit *)o;
commit->object.flags |= COMPLETE;
insert_by_date(commit, &complete);
diff --git a/git-count-objects.sh b/git-count-objects.sh
index 74ee4f371f..843d2fd9f2 100755
--- a/git-count-objects.sh
+++ b/git-count-objects.sh
@@ -2,7 +2,7 @@
. git-sh-setup
-echo $(find "$GIT_DIR/objects"/?? -type f -print | wc -l) objects, \
+echo $(find "$GIT_DIR/objects"/?? -type f -print 2>/dev/null | wc -l) objects, \
$({
echo 0
# "no-such" is to help Darwin folks by not using xargs -r.
diff --git a/http-fetch.c b/http-fetch.c
index efa6e82329..a7dc2cc3bd 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -100,6 +100,8 @@ static char *ssl_key = NULL;
static char *ssl_capath = NULL;
#endif
static char *ssl_cainfo = NULL;
+static long curl_low_speed_limit = -1;
+static long curl_low_speed_time = -1;
struct buffer
{
@@ -158,6 +160,17 @@ static int http_options(const char *var, const char *value)
}
#endif
+ if (!strcmp("http.lowspeedlimit", var)) {
+ if (curl_low_speed_limit == -1)
+ curl_low_speed_limit = (long)git_config_int(var, value);
+ return 0;
+ }
+ if (!strcmp("http.lowspeedtime", var)) {
+ if (curl_low_speed_time == -1)
+ curl_low_speed_time = (long)git_config_int(var, value);
+ return 0;
+ }
+
/* Fall back on the default ones */
return git_default_config(var, value);
}
@@ -246,6 +259,13 @@ static CURL* get_curl_handle(void)
curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
+ if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
+ curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
+ curl_low_speed_limit);
+ curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME,
+ curl_low_speed_time);
+ }
+
return result;
}
@@ -1177,6 +1197,8 @@ int main(int argc, char **argv)
char *url;
int arg = 1;
struct active_request_slot *slot;
+ char *low_speed_limit;
+ char *low_speed_time;
while (arg < argc && argv[arg][0] == '-') {
if (argv[arg][1] == 't') {
@@ -1232,6 +1254,13 @@ int main(int argc, char **argv)
#endif
ssl_cainfo = getenv("GIT_SSL_CAINFO");
+ low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
+ if (low_speed_limit != NULL)
+ curl_low_speed_limit = strtol(low_speed_limit, NULL, 10);
+ low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME");
+ if (low_speed_time != NULL)
+ curl_low_speed_time = strtol(low_speed_time, NULL, 10);
+
git_config(http_options);
if (curl_ssl_verify == -1)
diff --git a/sha1_name.c b/sha1_name.c
index 75c688ecf2..cc320d3d7f 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -323,6 +323,8 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
return -1;
if (!type_string) {
o = deref_tag(o);
+ if (!o || (!o->parsed && !parse_object(o->sha1)))
+ return -1;
memcpy(sha1, o->sha1, 20);
}
else {
@@ -332,7 +334,7 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
*/
while (1) {
- if (!o)
+ if (!o || (!o->parsed && !parse_object(o->sha1)))
return -1;
if (o->type == type_string) {
memcpy(sha1, o->sha1, 20);
diff --git a/upload-pack.c b/upload-pack.c
index 21b4b8b757..8a41cafaaa 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -4,13 +4,19 @@
#include "tag.h"
#include "object.h"
-static const char upload_pack_usage[] = "git-upload-pack <dir>";
+static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=nn] <dir>";
#define MAX_HAS (16)
#define MAX_NEEDS (256)
static int nr_has = 0, nr_needs = 0;
static unsigned char has_sha1[MAX_HAS][20];
static unsigned char needs_sha1[MAX_NEEDS][20];
+static unsigned int timeout = 0;
+
+static void reset_timeout(void)
+{
+ alarm(timeout);
+}
static int strip(char *line, int len)
{
@@ -100,6 +106,7 @@ static int get_common_commits(void)
for(;;) {
len = packet_read_line(0, line, sizeof(line));
+ reset_timeout();
if (!len) {
packet_write(1, "NAK\n");
@@ -122,6 +129,7 @@ static int get_common_commits(void)
for (;;) {
len = packet_read_line(0, line, sizeof(line));
+ reset_timeout();
if (!len)
continue;
len = strip(line, len);
@@ -145,6 +153,7 @@ static int receive_needs(void)
for (;;) {
unsigned char dummy[20], *sha1_buf;
len = packet_read_line(0, line, sizeof(line));
+ reset_timeout();
if (!len)
return needs;
@@ -179,6 +188,7 @@ static int send_ref(const char *refname, const unsigned char *sha1)
static int upload_pack(void)
{
+ reset_timeout();
head_ref(send_ref);
for_each_ref(send_ref);
packet_flush(1);
@@ -193,18 +203,43 @@ static int upload_pack(void)
int main(int argc, char **argv)
{
const char *dir;
- if (argc != 2)
+ int i;
+ int strict = 0;
+
+ for (i = 1; i < argc; i++) {
+ char *arg = argv[i];
+
+ if (arg[0] != '-')
+ break;
+ if (!strcmp(arg, "--strict")) {
+ strict = 1;
+ continue;
+ }
+ if (!strncmp(arg, "--timeout=", 10)) {
+ timeout = atoi(arg+10);
+ continue;
+ }
+ if (!strcmp(arg, "--")) {
+ i++;
+ break;
+ }
+ }
+
+ if (i != argc-1)
usage(upload_pack_usage);
- dir = argv[1];
+ dir = argv[i];
/* chdir to the directory. If that fails, try appending ".git" */
if (chdir(dir) < 0) {
- if (chdir(mkpath("%s.git", dir)) < 0)
+ if (strict || chdir(mkpath("%s.git", dir)) < 0)
die("git-upload-pack unable to chdir to %s", dir);
}
- chdir(".git");
+ if (!strict)
+ chdir(".git");
+
if (access("objects", X_OK) || access("refs", X_OK))
die("git-upload-pack: %s doesn't seem to be a git archive", dir);
+
putenv("GIT_DIR=.");
upload_pack();
return 0;