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

Merge branch 'pb/multi-fetch'

* pb/multi-fetch:
  Teach git-http-fetch the --stdin switch
  Teach git-local-fetch the --stdin switch
  Make pull() support fetching multiple targets at once
  Make pull() take some implicit data as explicit arguments
......@@ -8,7 +8,7 @@ git-http-fetch - downloads a remote git repository via HTTP
SYNOPSIS
--------
'git-http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] <commit> <url>
'git-http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url>
DESCRIPTION
-----------
......@@ -33,6 +33,12 @@ commit-id::
Writes the commit-id into the filename under $GIT_DIR/refs/<filename> on
the local end after the transfer is complete.
--stdin::
Instead of a commit id on the commandline (which is not expected in this
case), 'git-http-fetch' expects lines on stdin in the format
<commit-id>['\t'<filename-as-in--w>]
Author
------
Written by Linus Torvalds <torvalds@osdl.org>
......
......@@ -29,6 +29,12 @@ OPTIONS
Writes the commit-id into the filename under $GIT_DIR/refs/<filename> on
the local end after the transfer is complete.
--stdin::
Instead of a commit id on the commandline (which is not expected in this
case), 'git-local-fetch' expects lines on stdin in the format
<commit-id>['\t'<filename-as-in--w>]
Author
------
Written by Junio C Hamano <junkio@cox.net>
......
......@@ -7,9 +7,7 @@
#include "tag.h"
#include "blob.h"
#include "refs.h"
const char *write_ref = NULL;
const char *write_ref_log_details = NULL;
#include "strbuf.h"
int get_tree = 0;
int get_history = 0;
......@@ -213,54 +211,106 @@ static int mark_complete(const char *path, const unsigned char *sha1)
return 0;
}
int pull(char *target)
int pull_targets_stdin(char ***target, const char ***write_ref)
{
int targets = 0, targets_alloc = 0;
struct strbuf buf;
*target = NULL; *write_ref = NULL;
strbuf_init(&buf);
while (1) {
char *rf_one = NULL;
char *tg_one;
read_line(&buf, stdin, '\n');
if (buf.eof)
break;
tg_one = buf.buf;
rf_one = strchr(tg_one, '\t');
if (rf_one)
*rf_one++ = 0;
if (targets >= targets_alloc) {
targets_alloc = targets_alloc ? targets_alloc * 2 : 64;
*target = xrealloc(*target, targets_alloc * sizeof(**target));
*write_ref = xrealloc(*write_ref, targets_alloc * sizeof(**write_ref));
}
(*target)[targets] = strdup(tg_one);
(*write_ref)[targets] = rf_one ? strdup(rf_one) : NULL;
targets++;
}
return targets;
}
void pull_targets_free(int targets, char **target, const char **write_ref)
{
struct ref_lock *lock = NULL;
unsigned char sha1[20];
while (targets--) {
free(target[targets]);
if (write_ref[targets])
free((char *) write_ref[targets]);
}
}
int pull(int targets, char **target, const char **write_ref,
const char *write_ref_log_details)
{
struct ref_lock **lock = xcalloc(targets, sizeof(struct ref_lock *));
unsigned char *sha1 = xmalloc(targets * 20);
char *msg;
int ret;
int i;
save_commit_buffer = 0;
track_object_refs = 0;
if (write_ref) {
lock = lock_ref_sha1(write_ref, NULL, 0);
if (!lock) {
error("Can't lock ref %s", write_ref);
return -1;
for (i = 0; i < targets; i++) {
if (!write_ref[i])
continue;
lock[i] = lock_ref_sha1(write_ref[i], NULL, 0);
if (!lock[i]) {
error("Can't lock ref %s", write_ref[i]);
goto unlock_and_fail;
}
}
if (!get_recover)
for_each_ref(mark_complete);
if (interpret_target(target, sha1)) {
error("Could not interpret %s as something to pull", target);
if (lock)
unlock_ref(lock);
return -1;
for (i = 0; i < targets; i++) {
if (interpret_target(target[i], &sha1[20 * i])) {
error("Could not interpret %s as something to pull", target[i]);
goto unlock_and_fail;
}
if (process(lookup_unknown_object(&sha1[20 * i])))
goto unlock_and_fail;
}
if (process(lookup_unknown_object(sha1))) {
if (lock)
unlock_ref(lock);
return -1;
if (loop())
goto unlock_and_fail;
if (write_ref_log_details) {
msg = xmalloc(strlen(write_ref_log_details) + 12);
sprintf(msg, "fetch from %s", write_ref_log_details);
} else {
msg = NULL;
}
if (loop()) {
if (lock)
unlock_ref(lock);
return -1;
for (i = 0; i < targets; i++) {
if (!write_ref[i])
continue;
ret = write_ref_sha1(lock[i], &sha1[20 * i], msg ? msg : "fetch (unknown)");
lock[i] = NULL;
if (ret)
goto unlock_and_fail;
}
if (msg)
free(msg);
if (write_ref) {
if (write_ref_log_details) {
msg = xmalloc(strlen(write_ref_log_details) + 12);
sprintf(msg, "fetch from %s", write_ref_log_details);
}
else
msg = NULL;
ret = write_ref_sha1(lock, sha1, msg ? msg : "fetch (unknown)");
if (msg)
free(msg);
return ret;
}
return 0;
unlock_and_fail:
for (i = 0; i < targets; i++)
if (lock[i])
unlock_ref(lock[i]);
return -1;
}
......@@ -22,12 +22,6 @@ extern void prefetch(unsigned char *sha1);
*/
extern int fetch_ref(char *ref, unsigned char *sha1);
/* If set, the ref filename to write the target value to. */
extern const char *write_ref;
/* If set additional text will appear in the ref log. */
extern const char *write_ref_log_details;
/* Set to fetch the target tree. */
extern int get_tree;
......@@ -46,6 +40,15 @@ extern int get_recover;
/* Report what we got under get_verbosely */
extern void pull_say(const char *, const char *);
extern int pull(char *target);
/* Load pull targets from stdin */
extern int pull_targets_stdin(char ***target, const char ***write_ref);
/* Free up loaded targets */
extern void pull_targets_free(int targets, char **target, const char **write_ref);
/* If write_ref is set, the ref filename to write the target value to. */
/* If write_ref_log_details is set, additional text will appear in the ref log. */
extern int pull(int targets, char **target, const char **write_ref,
const char *write_ref_log_details);
#endif /* PULL_H */
......@@ -36,6 +36,8 @@ enum XML_Status {
#define PREV_BUF_SIZE 4096
#define RANGE_HEADER_SIZE 30
static int commits_on_stdin = 0;
static int got_alternates = -1;
static int corrupt_object_found = 0;
......@@ -43,7 +45,7 @@ static struct curl_slist *no_pragma_header;
struct alt_base
{
char *base;
const char *base;
int path_len;
int got_indices;
struct packed_git *packs;
......@@ -81,7 +83,7 @@ struct object_request
};
struct alternates_request {
char *base;
const char *base;
char *url;
struct buffer *buffer;
struct active_request_slot *slot;
......@@ -142,7 +144,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
return size;
}
static void fetch_alternates(char *base);
static void fetch_alternates(const char *base);
static void process_object_response(void *callback_data);
......@@ -507,7 +509,7 @@ static void process_alternates_response(void *callback_data)
(struct alternates_request *)callback_data;
struct active_request_slot *slot = alt_req->slot;
struct alt_base *tail = alt;
char *base = alt_req->base;
const char *base = alt_req->base;
static const char null_byte = '\0';
char *data;
int i = 0;
......@@ -612,7 +614,7 @@ static void process_alternates_response(void *callback_data)
got_alternates = 1;
}
static void fetch_alternates(char *base)
static void fetch_alternates(const char *base)
{
struct buffer buffer;
char *url;
......@@ -1185,7 +1187,7 @@ int fetch_ref(char *ref, unsigned char *sha1)
char *url;
char hex[42];
struct buffer buffer;
char *base = alt->base;
const char *base = alt->base;
struct active_request_slot *slot;
struct slot_results results;
buffer.size = 41;
......@@ -1214,10 +1216,12 @@ int fetch_ref(char *ref, unsigned char *sha1)
return 0;
}
int main(int argc, char **argv)
int main(int argc, const char **argv)
{
char *commit_id;
char *url;
int commits;
const char **write_ref = NULL;
char **commit_id;
const char *url;
char *path;
int arg = 1;
int rc = 0;
......@@ -1237,20 +1241,26 @@ int main(int argc, char **argv)
} else if (argv[arg][1] == 'v') {
get_verbosely = 1;
} else if (argv[arg][1] == 'w') {
write_ref = argv[arg + 1];
write_ref = &argv[arg + 1];
arg++;
} else if (!strcmp(argv[arg], "--recover")) {
get_recover = 1;
} else if (!strcmp(argv[arg], "--stdin")) {
commits_on_stdin = 1;
}
arg++;
}
if (argc < arg + 2) {
usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url");
if (argc < arg + 2 - commits_on_stdin) {
usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url");
return 1;
}
commit_id = argv[arg];
url = argv[arg + 1];
write_ref_log_details = url;
if (commits_on_stdin) {
commits = pull_targets_stdin(&commit_id, &write_ref);
} else {
commit_id = (char **) &argv[arg++];
commits = 1;
}
url = argv[arg];
http_init();
......@@ -1268,13 +1278,16 @@ int main(int argc, char **argv)
alt->path_len = strlen(path);
}
if (pull(commit_id))
if (pull(commits, commit_id, write_ref, url))
rc = 1;
http_cleanup();
curl_slist_free_all(no_pragma_header);
if (commits_on_stdin)
pull_targets_free(commits, commit_id, write_ref);
if (corrupt_object_found) {
fprintf(stderr,
"Some loose object were found to be corrupt, but they might be just\n"
......
......@@ -8,8 +8,9 @@
static int use_link = 0;
static int use_symlink = 0;
static int use_filecopy = 1;
static int commits_on_stdin = 0;
static char *path; /* "Remote" git repository */
static const char *path; /* "Remote" git repository */
void prefetch(unsigned char *sha1)
{
......@@ -194,7 +195,7 @@ int fetch_ref(char *ref, unsigned char *sha1)
}
static const char local_pull_usage[] =
"git-local-fetch [-c] [-t] [-a] [-v] [-w filename] [--recover] [-l] [-s] [-n] commit-id path";
"git-local-fetch [-c] [-t] [-a] [-v] [-w filename] [--recover] [-l] [-s] [-n] [--stdin] commit-id path";
/*
* By default we only use file copy.
......@@ -202,9 +203,11 @@ static const char local_pull_usage[] =
* If -s is specified, then a symlink is attempted.
* If -n is _not_ specified, then a regular file-to-file copy is done.
*/
int main(int argc, char **argv)
int main(int argc, const char **argv)
{
char *commit_id;
int commits;
const char **write_ref = NULL;
char **commit_id;
int arg = 1;
setup_git_directory();
......@@ -229,21 +232,30 @@ int main(int argc, char **argv)
else if (argv[arg][1] == 'v')
get_verbosely = 1;
else if (argv[arg][1] == 'w')
write_ref = argv[++arg];
write_ref = &argv[++arg];
else if (!strcmp(argv[arg], "--recover"))
get_recover = 1;
else if (!strcmp(argv[arg], "--stdin"))
commits_on_stdin = 1;
else
usage(local_pull_usage);
arg++;
}
if (argc < arg + 2)
if (argc < arg + 2 - commits_on_stdin)
usage(local_pull_usage);
commit_id = argv[arg];
path = argv[arg + 1];
write_ref_log_details = path;
if (commits_on_stdin) {
commits = pull_targets_stdin(&commit_id, &write_ref);
} else {
commit_id = (char **) &argv[arg++];
commits = 1;
}
path = argv[arg];
if (pull(commit_id))
if (pull(commits, commit_id, write_ref, path))
return 1;
if (commits_on_stdin)
pull_targets_free(commits, commit_id, write_ref);
return 0;
}
......@@ -123,6 +123,7 @@ static const char ssh_fetch_usage[] =
" [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url";
int main(int argc, char **argv)
{
const char *write_ref = NULL;
char *commit_id;
char *url;
int arg = 1;
......@@ -159,7 +160,6 @@ int main(int argc, char **argv)
}
commit_id = argv[arg];
url = argv[arg + 1];
write_ref_log_details = url;
if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1))
return 1;
......@@ -167,7 +167,7 @@ int main(int argc, char **argv)
if (get_version())
return 1;
if (pull(commit_id))
if (pull(1, &commit_id, &write_ref, url))
return 1;
return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册