* [PATCH 5/6] http-push: support for updating remote info/refs
From: Nick Hengeveld @ 2006-03-11 4:18 UTC (permalink / raw)
To: git
If info/refs exists on the remote, get a lock on info/refs, make sure that
there is a local copy of the object referenced in each remote ref (in case
someone else added a tag we don't have locally), do all the refspec updates,
and generate and send an updated info/refs file.
---
http-push.c | 547 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 536 insertions(+), 11 deletions(-)
b29c6a3ec299241894a3effd8cea4d00ea117a8c
diff --git a/http-push.c b/http-push.c
index ece40da..65c6664 100644
--- a/http-push.c
+++ b/http-push.c
@@ -22,6 +22,7 @@ enum XML_Status {
#define XML_STATUS_ERROR 0
#endif
+#define PREV_BUF_SIZE 4096
#define RANGE_HEADER_SIZE 30
/* DAV methods */
@@ -58,9 +59,10 @@ enum XML_Status {
/* bits #0-4 in revision.h */
-#define LOCAL (1u << 5)
-#define REMOTE (1u << 6)
-#define PUSHING (1u << 7)
+#define LOCAL (1u << 5)
+#define REMOTE (1u << 6)
+#define FETCHING (1u << 7)
+#define PUSHING (1u << 8)
static int pushing = 0;
static int aborted = 0;
@@ -79,6 +81,9 @@ struct repo
{
char *url;
int path_len;
+ int has_info_refs;
+ int can_update_info_refs;
+ int has_info_packs;
struct packed_git *packs;
struct remote_lock *locks;
};
@@ -86,6 +91,9 @@ struct repo
static struct repo *remote = NULL;
enum transfer_state {
+ NEED_FETCH,
+ RUN_FETCH_LOOSE,
+ RUN_FETCH_PACKED,
NEED_PUSH,
RUN_MKCOL,
RUN_PUT,
@@ -104,6 +112,8 @@ struct transfer_request
struct buffer buffer;
char filename[PATH_MAX];
char tmpfile[PATH_MAX];
+ int local_fileno;
+ FILE *local_stream;
enum transfer_state state;
CURLcode curl_result;
char errorstr[CURL_ERROR_SIZE];
@@ -113,6 +123,7 @@ struct transfer_request
z_stream stream;
int zret;
int rename;
+ void *userData;
struct active_request_slot *slot;
struct transfer_request *next;
};
@@ -159,6 +170,7 @@ struct remote_ls_ctx
};
static void finish_request(struct transfer_request *request);
+static void release_request(struct transfer_request *request);
static void process_response(void *callback_data)
{
@@ -168,6 +180,258 @@ static void process_response(void *callb
finish_request(request);
}
+static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
+ void *data)
+{
+ unsigned char expn[4096];
+ size_t size = eltsize * nmemb;
+ int posn = 0;
+ struct transfer_request *request = (struct transfer_request *)data;
+ do {
+ ssize_t retval = write(request->local_fileno,
+ ptr + posn, size - posn);
+ if (retval < 0)
+ return posn;
+ posn += retval;
+ } while (posn < size);
+
+ request->stream.avail_in = size;
+ request->stream.next_in = ptr;
+ do {
+ request->stream.next_out = expn;
+ request->stream.avail_out = sizeof(expn);
+ request->zret = inflate(&request->stream, Z_SYNC_FLUSH);
+ SHA1_Update(&request->c, expn,
+ sizeof(expn) - request->stream.avail_out);
+ } while (request->stream.avail_in && request->zret == Z_OK);
+ data_received++;
+ return size;
+}
+
+static void start_fetch_loose(struct transfer_request *request)
+{
+ char *hex = sha1_to_hex(request->obj->sha1);
+ char *filename;
+ char prevfile[PATH_MAX];
+ char *url;
+ char *posn;
+ int prevlocal;
+ unsigned char prev_buf[PREV_BUF_SIZE];
+ ssize_t prev_read = 0;
+ long prev_posn = 0;
+ char range[RANGE_HEADER_SIZE];
+ struct curl_slist *range_header = NULL;
+ struct active_request_slot *slot;
+
+ filename = sha1_file_name(request->obj->sha1);
+ snprintf(request->filename, sizeof(request->filename), "%s", filename);
+ snprintf(request->tmpfile, sizeof(request->tmpfile),
+ "%s.temp", filename);
+
+ snprintf(prevfile, sizeof(prevfile), "%s.prev", request->filename);
+ unlink(prevfile);
+ rename(request->tmpfile, prevfile);
+ unlink(request->tmpfile);
+
+ if (request->local_fileno != -1)
+ error("fd leakage in start: %d", request->local_fileno);
+ request->local_fileno = open(request->tmpfile,
+ O_WRONLY | O_CREAT | O_EXCL, 0666);
+ /* This could have failed due to the "lazy directory creation";
+ * try to mkdir the last path component.
+ */
+ if (request->local_fileno < 0 && errno == ENOENT) {
+ char *dir = strrchr(request->tmpfile, '/');
+ if (dir) {
+ *dir = 0;
+ mkdir(request->tmpfile, 0777);
+ *dir = '/';
+ }
+ request->local_fileno = open(request->tmpfile,
+ O_WRONLY | O_CREAT | O_EXCL, 0666);
+ }
+
+ if (request->local_fileno < 0) {
+ request->state = ABORTED;
+ error("Couldn't create temporary file %s for %s: %s",
+ request->tmpfile, request->filename, strerror(errno));
+ return;
+ }
+
+ memset(&request->stream, 0, sizeof(request->stream));
+
+ inflateInit(&request->stream);
+
+ SHA1_Init(&request->c);
+
+ url = xmalloc(strlen(remote->url) + 50);
+ request->url = xmalloc(strlen(remote->url) + 50);
+ strcpy(url, remote->url);
+ posn = url + strlen(remote->url);
+ strcpy(posn, "objects/");
+ posn += 8;
+ memcpy(posn, hex, 2);
+ posn += 2;
+ *(posn++) = '/';
+ strcpy(posn, hex + 2);
+ strcpy(request->url, url);
+
+ /* If a previous temp file is present, process what was already
+ fetched. */
+ prevlocal = open(prevfile, O_RDONLY);
+ if (prevlocal != -1) {
+ do {
+ prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE);
+ if (prev_read>0) {
+ if (fwrite_sha1_file(prev_buf,
+ 1,
+ prev_read,
+ request) == prev_read) {
+ prev_posn += prev_read;
+ } else {
+ prev_read = -1;
+ }
+ }
+ } while (prev_read > 0);
+ close(prevlocal);
+ }
+ unlink(prevfile);
+
+ /* Reset inflate/SHA1 if there was an error reading the previous temp
+ file; also rewind to the beginning of the local file. */
+ if (prev_read == -1) {
+ memset(&request->stream, 0, sizeof(request->stream));
+ inflateInit(&request->stream);
+ SHA1_Init(&request->c);
+ if (prev_posn>0) {
+ prev_posn = 0;
+ lseek(request->local_fileno, SEEK_SET, 0);
+ ftruncate(request->local_fileno, 0);
+ }
+ }
+
+ slot = get_active_slot();
+ slot->callback_func = process_response;
+ slot->callback_data = request;
+ request->slot = slot;
+
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, request);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
+ curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
+
+ /* If we have successfully processed data from a previous fetch
+ attempt, only fetch the data we don't already have. */
+ if (prev_posn>0) {
+ if (push_verbosely)
+ fprintf(stderr,
+ "Resuming fetch of object %s at byte %ld\n",
+ hex, prev_posn);
+ sprintf(range, "Range: bytes=%ld-", prev_posn);
+ range_header = curl_slist_append(range_header, range);
+ curl_easy_setopt(slot->curl,
+ CURLOPT_HTTPHEADER, range_header);
+ }
+
+ /* Try to get the request started, abort the request on error */
+ request->state = RUN_FETCH_LOOSE;
+ if (!start_active_slot(slot)) {
+ fprintf(stderr, "Unable to start GET request\n");
+ remote->can_update_info_refs = 0;
+ release_request(request);
+ }
+}
+
+static void start_fetch_packed(struct transfer_request *request)
+{
+ char *url;
+ struct packed_git *target;
+ FILE *packfile;
+ char *filename;
+ long prev_posn = 0;
+ char range[RANGE_HEADER_SIZE];
+ struct curl_slist *range_header = NULL;
+
+ struct transfer_request *check_request = request_queue_head;
+ struct active_request_slot *slot;
+
+ target = find_sha1_pack(request->obj->sha1, remote->packs);
+ if (!target) {
+ fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
+ remote->can_update_info_refs = 0;
+ release_request(request);
+ return;
+ }
+
+ fprintf(stderr, "Fetching pack %s\n", sha1_to_hex(target->sha1));
+ fprintf(stderr, " which contains %s\n", sha1_to_hex(request->obj->sha1));
+
+ filename = sha1_pack_name(target->sha1);
+ snprintf(request->filename, sizeof(request->filename), "%s", filename);
+ snprintf(request->tmpfile, sizeof(request->tmpfile),
+ "%s.temp", filename);
+
+ url = xmalloc(strlen(remote->url) + 64);
+ sprintf(url, "%sobjects/pack/pack-%s.pack",
+ remote->url, sha1_to_hex(target->sha1));
+
+ /* Make sure there isn't another open request for this pack */
+ while (check_request) {
+ if (check_request->state == RUN_FETCH_PACKED &&
+ !strcmp(check_request->url, url)) {
+ free(url);
+ release_request(request);
+ return;
+ }
+ check_request = check_request->next;
+ }
+
+ packfile = fopen(request->tmpfile, "a");
+ if (!packfile) {
+ fprintf(stderr, "Unable to open local file %s for pack",
+ filename);
+ remote->can_update_info_refs = 0;
+ free(url);
+ return;
+ }
+
+ slot = get_active_slot();
+ slot->callback_func = process_response;
+ slot->callback_data = request;
+ request->slot = slot;
+ request->local_stream = packfile;
+ request->userData = target;
+
+ request->url = url;
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, packfile);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
+ slot->local = packfile;
+
+ /* If there is data present from a previous transfer attempt,
+ resume where it left off */
+ prev_posn = ftell(packfile);
+ if (prev_posn>0) {
+ if (push_verbosely)
+ fprintf(stderr,
+ "Resuming fetch of pack %s at byte %ld\n",
+ sha1_to_hex(target->sha1), prev_posn);
+ sprintf(range, "Range: bytes=%ld-", prev_posn);
+ range_header = curl_slist_append(range_header, range);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
+ }
+
+ /* Try to get the request started, abort the request on error */
+ request->state = RUN_FETCH_PACKED;
+ if (!start_active_slot(slot)) {
+ fprintf(stderr, "Unable to start GET request\n");
+ remote->can_update_info_refs = 0;
+ release_request(request);
+ }
+}
+
static void start_mkcol(struct transfer_request *request)
{
char *hex = sha1_to_hex(request->obj->sha1);
@@ -388,6 +652,10 @@ static void release_request(struct trans
entry->next = entry->next->next;
}
+ if (request->local_fileno != -1)
+ close(request->local_fileno);
+ if (request->local_stream)
+ fclose(request->local_stream);
if (request->url != NULL)
free(request->url);
free(request);
@@ -395,7 +663,11 @@ static void release_request(struct trans
static void finish_request(struct transfer_request *request)
{
- request->curl_result = request->slot->curl_result;
+ struct stat st;
+ struct packed_git *target;
+ struct packed_git **lst;
+
+ request->curl_result = request->slot->curl_result;
request->http_code = request->slot->http_code;
request->slot = NULL;
@@ -437,7 +709,6 @@ static void finish_request(struct transf
if (request->curl_result == CURLE_OK) {
fprintf(stderr, " sent %s\n",
sha1_to_hex(request->obj->sha1));
- request->state = COMPLETE;
request->obj->flags |= REMOTE;
release_request(request);
} else {
@@ -447,12 +718,73 @@ static void finish_request(struct transf
request->state = ABORTED;
aborted = 1;
}
+ } else if (request->state == RUN_FETCH_LOOSE) {
+ fchmod(request->local_fileno, 0444);
+ close(request->local_fileno); request->local_fileno = -1;
+
+ if (request->curl_result != CURLE_OK &&
+ request->http_code != 416) {
+ if (stat(request->tmpfile, &st) == 0) {
+ if (st.st_size == 0)
+ unlink(request->tmpfile);
+ }
+ } else {
+ if (request->http_code == 416)
+ fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
+
+ inflateEnd(&request->stream);
+ SHA1_Final(request->real_sha1, &request->c);
+ if (request->zret != Z_STREAM_END) {
+ unlink(request->tmpfile);
+ } else if (memcmp(request->obj->sha1, request->real_sha1, 20)) {
+ unlink(request->tmpfile);
+ } else {
+ request->rename =
+ move_temp_to_file(
+ request->tmpfile,
+ request->filename);
+ if (request->rename == 0) {
+ request->obj->flags |= (LOCAL | REMOTE);
+ }
+ }
+ }
+
+ /* Try fetching packed if necessary */
+ if (request->obj->flags & LOCAL)
+ release_request(request);
+ else
+ start_fetch_packed(request);
+
+ } else if (request->state == RUN_FETCH_PACKED) {
+ if (request->curl_result != CURLE_OK) {
+ fprintf(stderr, "Unable to get pack file %s\n%s",
+ request->url, curl_errorstr);
+ remote->can_update_info_refs = 0;
+ } else {
+ fclose(request->local_stream);
+ request->local_stream = NULL;
+ if (!move_temp_to_file(request->tmpfile,
+ request->filename)) {
+ target = (struct packed_git *)request->userData;
+ lst = &remote->packs;
+ while (*lst != target)
+ lst = &((*lst)->next);
+ *lst = (*lst)->next;
+
+ if (!verify_pack(target, 0))
+ install_packed_git(target);
+ else
+ remote->can_update_info_refs = 0;
+ }
+ }
+ release_request(request);
}
}
void fill_active_slots(void)
{
struct transfer_request *request = request_queue_head;
+ struct transfer_request *next;
struct active_request_slot *slot = active_queue_head;
int num_transfers;
@@ -460,7 +792,10 @@ void fill_active_slots(void)
return;
while (active_requests < max_requests && request != NULL) {
- if (pushing && request->state == NEED_PUSH) {
+ next = request->next;
+ if (request->state == NEED_FETCH) {
+ start_fetch_loose(request);
+ } else if (pushing && request->state == NEED_PUSH) {
if (remote_dir_exists[request->obj->sha1[0]] == 1) {
start_put(request);
} else {
@@ -468,7 +803,7 @@ void fill_active_slots(void)
}
curl_multi_perform(curlm, &num_transfers);
}
- request = request->next;
+ request = next;
}
while (slot != NULL) {
@@ -482,7 +817,38 @@ void fill_active_slots(void)
static void get_remote_object_list(unsigned char parent);
-static void add_request(struct object *obj, struct remote_lock *lock)
+static void add_fetch_request(struct object *obj)
+{
+ struct transfer_request *request;
+
+ check_locks();
+
+ /*
+ * Don't fetch the object if it's known to exist locally
+ * or is already in the request queue
+ */
+ if (remote_dir_exists[obj->sha1[0]] == -1)
+ get_remote_object_list(obj->sha1[0]);
+ if (obj->flags & (LOCAL | FETCHING))
+ return;
+
+ obj->flags |= FETCHING;
+ request = xmalloc(sizeof(*request));
+ request->obj = obj;
+ request->url = NULL;
+ request->lock = NULL;
+ request->headers = NULL;
+ request->local_fileno = -1;
+ request->local_stream = NULL;
+ request->state = NEED_FETCH;
+ request->next = request_queue_head;
+ request_queue_head = request;
+
+ fill_active_slots();
+ step_active_slots();
+}
+
+static void add_send_request(struct object *obj, struct remote_lock *lock)
{
struct transfer_request *request = request_queue_head;
struct packed_git *target;
@@ -510,6 +876,8 @@ static void add_request(struct object *o
request->url = NULL;
request->lock = lock;
request->headers = NULL;
+ request->local_fileno = -1;
+ request->local_stream = NULL;
request->state = NEED_PUSH;
request->next = request_queue_head;
request_queue_head = request;
@@ -1375,7 +1743,7 @@ static void get_delta(struct rev_info *r
p = process_tree(commit->tree, p, NULL, "");
commit->object.flags |= LOCAL;
if (!(commit->object.flags & UNINTERESTING))
- add_request(&commit->object, lock);
+ add_send_request(&commit->object, lock);
}
for (pending = revs->pending_objects; pending; pending = pending->next) {
@@ -1402,7 +1770,7 @@ static void get_delta(struct rev_info *r
while (objects) {
if (!(objects->item->flags & UNINTERESTING))
- add_request(objects->item, lock);
+ add_send_request(objects->item, lock);
objects = objects->next;
}
}
@@ -1483,6 +1851,7 @@ static void one_remote_ref(char *refname
{
struct ref *ref;
unsigned char remote_sha1[20];
+ struct object *obj;
if (fetch_ref(refname, remote_sha1) != 0) {
fprintf(stderr,
@@ -1491,6 +1860,19 @@ static void one_remote_ref(char *refname
return;
}
+ /*
+ * Fetch a copy of the object if it doesn't exist locally - it
+ * may be required for updating server info later.
+ */
+ if (remote->can_update_info_refs && !has_sha1_file(remote_sha1)) {
+ obj = lookup_unknown_object(remote_sha1);
+ if (obj) {
+ fprintf(stderr, " fetch %s for %s\n",
+ sha1_to_hex(remote_sha1), refname);
+ add_fetch_request(obj);
+ }
+ }
+
int len = strlen(refname) + 1;
ref = xcalloc(1, sizeof(*ref) + len);
memcpy(ref->old_sha1, remote_sha1, 20);
@@ -1596,6 +1978,125 @@ static void mark_edges_uninteresting(str
}
}
+static void add_remote_info_ref(struct remote_ls_ctx *ls)
+{
+ struct buffer *buf = (struct buffer *)ls->userData;
+ unsigned char remote_sha1[20];
+ struct object *o;
+ int len;
+ char *ref_info;
+
+ if (fetch_ref(ls->dentry_name, remote_sha1) != 0) {
+ fprintf(stderr,
+ "Unable to fetch ref %s from %s\n",
+ ls->dentry_name, remote->url);
+ aborted = 1;
+ return;
+ }
+
+ o = parse_object(remote_sha1);
+ if (!o) {
+ fprintf(stderr,
+ "Unable to parse object %s for remote ref %s\n",
+ sha1_to_hex(remote_sha1), ls->dentry_name);
+ aborted = 1;
+ return;
+ }
+
+ len = strlen(ls->dentry_name) + 42;
+ ref_info = xcalloc(len + 1, 1);
+ sprintf(ref_info, "%s %s\n",
+ sha1_to_hex(remote_sha1), ls->dentry_name);
+ fwrite_buffer(ref_info, 1, len, buf);
+ free(ref_info);
+
+ if (o->type == tag_type) {
+ o = deref_tag(o, ls->dentry_name, 0);
+ if (o) {
+ len = strlen(ls->dentry_name) + 45;
+ ref_info = xcalloc(len + 1, 1);
+ sprintf(ref_info, "%s %s^{}\n",
+ sha1_to_hex(o->sha1), ls->dentry_name);
+ fwrite_buffer(ref_info, 1, len, buf);
+ free(ref_info);
+ }
+ }
+}
+
+static void update_remote_info_refs(struct remote_lock *lock)
+{
+ struct buffer buffer;
+ struct active_request_slot *slot;
+ struct slot_results results;
+ char *if_header;
+ struct curl_slist *dav_headers = NULL;
+
+ buffer.buffer = xmalloc(4096);
+ memset(buffer.buffer, 0, 4096);
+ buffer.size = 4096;
+ buffer.posn = 0;
+ remote_ls("refs/", (PROCESS_FILES | RECURSIVE),
+ add_remote_info_ref, &buffer);
+ if (!aborted) {
+ if_header = xmalloc(strlen(lock->token) + 25);
+ sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
+ dav_headers = curl_slist_append(dav_headers, if_header);
+
+ slot = get_active_slot();
+ slot->results = &results;
+ curl_easy_setopt(slot->curl, CURLOPT_INFILE, &buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, buffer.posn);
+ curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
+ curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
+ curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
+ curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
+
+ buffer.posn = 0;
+
+ if (start_active_slot(slot)) {
+ run_active_slot(slot);
+ if (results.curl_result != CURLE_OK) {
+ fprintf(stderr,
+ "PUT error: curl result=%d, HTTP code=%ld\n",
+ results.curl_result, results.http_code);
+ }
+ }
+ free(if_header);
+ }
+ free(buffer.buffer);
+}
+
+static int remote_exists(const char *path)
+{
+ char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
+ struct active_request_slot *slot;
+ struct slot_results results;
+
+ sprintf(url, "%s%s", remote->url, path);
+
+ slot = get_active_slot();
+ slot->results = &results;
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+ curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
+
+ if (start_active_slot(slot)) {
+ run_active_slot(slot);
+ if (results.http_code == 404)
+ return 0;
+ else if (results.curl_result == CURLE_OK)
+ return 1;
+ else
+ fprintf(stderr, "HEAD HTTP error %ld\n", results.http_code);
+ } else {
+ fprintf(stderr, "Unable to start HEAD request\n");
+ }
+
+ return -1;
+}
+
int main(int argc, char **argv)
{
struct transfer_request *request;
@@ -1603,6 +2104,7 @@ int main(int argc, char **argv)
int nr_refspec = 0;
char **refspec = NULL;
struct remote_lock *ref_lock = NULL;
+ struct remote_lock *info_ref_lock = NULL;
struct rev_info revs;
int rc = 0;
int i;
@@ -1667,6 +2169,18 @@ int main(int argc, char **argv)
goto cleanup;
}
+ /* Check whether the remote has server info files */
+ remote->can_update_info_refs = 0;
+ remote->has_info_refs = remote_exists("info/refs");
+ remote->has_info_packs = remote_exists("objects/info/packs");
+ if (remote->has_info_refs) {
+ info_ref_lock = lock_remote("info/refs", LOCK_TIME);
+ if (info_ref_lock)
+ remote->can_update_info_refs = 1;
+ }
+ if (remote->has_info_packs)
+ fetch_indices();
+
/* Get a list of all local and remote heads to validate refspecs */
get_local_heads();
fprintf(stderr, "Fetching remote heads...\n");
@@ -1769,7 +2283,6 @@ int main(int argc, char **argv)
pushing = 0;
prepare_revision_walk(&revs);
mark_edges_uninteresting(revs.commits);
- fetch_indices();
get_delta(&revs, ref_lock);
finish_all_active_slots();
@@ -1792,6 +2305,18 @@ int main(int argc, char **argv)
check_locks();
}
+ /* Update remote server info if appropriate */
+ if (remote->has_info_refs && new_refs) {
+ if (info_ref_lock && remote->can_update_info_refs) {
+ fprintf(stderr, "Updating remote server info\n");
+ update_remote_info_refs(info_ref_lock);
+ } else {
+ fprintf(stderr, "Unable to update server info\n");
+ }
+ }
+ if (info_ref_lock)
+ unlock_remote(info_ref_lock);
+
cleanup:
free(remote);
--
1.2.4.g8e81-dirty
^ permalink raw reply related
* [PATCH 3/6] http-push: refactor remote file/directory processing
From: Nick Hengeveld @ 2006-03-11 4:18 UTC (permalink / raw)
To: git
Replace single-use functions with one that can get a list of remote
collections and pass file/directory information to user-defined functions
for processing.
---
http-push.c | 245 ++++++++++++++++++++++++++---------------------------------
1 files changed, 107 insertions(+), 138 deletions(-)
05c0fc457388309cf12f3647a48071845acc2c70
diff --git a/http-push.c b/http-push.c
index 1b0b3a8..755bcb8 100644
--- a/http-push.c
+++ b/http-push.c
@@ -140,11 +140,23 @@ struct remote_lock
struct remote_lock *next;
};
-struct remote_dentry
+/* Flags that control remote_ls processing */
+#define PROCESS_FILES (1u << 0)
+#define PROCESS_DIRS (1u << 1)
+#define RECURSIVE (1u << 2)
+
+/* Flags that remote_ls passes to callback functions */
+#define IS_DIR (1u << 0)
+
+struct remote_ls_ctx
{
- char *base;
- char *name;
- int is_dir;
+ char *path;
+ void (*userFunc)(struct remote_ls_ctx *ls);
+ void *userData;
+ int flags;
+ char *dentry_name;
+ int dentry_flags;
+ struct remote_ls_ctx *parent;
};
static void finish_request(struct transfer_request *request);
@@ -812,55 +824,6 @@ static void handle_new_lock_ctx(struct x
}
static void one_remote_ref(char *refname);
-static void crawl_remote_refs(char *path);
-
-static void handle_crawl_ref_ctx(struct xml_ctx *ctx, int tag_closed)
-{
- struct remote_dentry *dentry = (struct remote_dentry *)ctx->userData;
-
-
- if (tag_closed) {
- if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && dentry->name) {
- if (dentry->is_dir) {
- if (strcmp(dentry->name, dentry->base)) {
- crawl_remote_refs(dentry->name);
- }
- } else {
- one_remote_ref(dentry->name);
- }
- } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
- dentry->name = xmalloc(strlen(ctx->cdata) -
- remote->path_len + 1);
- strcpy(dentry->name,
- ctx->cdata + remote->path_len);
- } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
- dentry->is_dir = 1;
- }
- } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
- dentry->name = NULL;
- dentry->is_dir = 0;
- }
-}
-
-static void handle_remote_object_list_ctx(struct xml_ctx *ctx, int tag_closed)
-{
- char *path;
- char *obj_hex;
-
- if (tag_closed) {
- if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
- path = ctx->cdata + remote->path_len;
- if (strlen(path) != 50)
- return;
- path += 9;
- obj_hex = xmalloc(strlen(path));
- strncpy(obj_hex, path, 2);
- strcpy(obj_hex + 2, path + 3);
- one_remote_object(obj_hex);
- free(obj_hex);
- }
- }
-}
static void
xml_start_tag(void *userData, const char *name, const char **atts)
@@ -1101,91 +1064,83 @@ static int unlock_remote(struct remote_l
return rc;
}
-static void crawl_remote_refs(char *path)
-{
- char *url;
- struct active_request_slot *slot;
- struct slot_results results;
- struct buffer in_buffer;
- struct buffer out_buffer;
- char *in_data;
- char *out_data;
- XML_Parser parser = XML_ParserCreate(NULL);
- enum XML_Status result;
- struct curl_slist *dav_headers = NULL;
- struct xml_ctx ctx;
- struct remote_dentry dentry;
-
- fprintf(stderr, " %s\n", path);
+static void remote_ls(const char *path, int flags,
+ void (*userFunc)(struct remote_ls_ctx *ls),
+ void *userData);
- dentry.base = path;
- dentry.name = NULL;
- dentry.is_dir = 0;
-
- url = xmalloc(strlen(remote->url) + strlen(path) + 1);
- sprintf(url, "%s%s", remote->url, path);
+static void process_ls_object(struct remote_ls_ctx *ls)
+{
+ unsigned int *parent = (unsigned int *)ls->userData;
+ char *path = ls->dentry_name;
+ char *obj_hex;
- out_buffer.size = strlen(PROPFIND_ALL_REQUEST);
- out_data = xmalloc(out_buffer.size + 1);
- snprintf(out_data, out_buffer.size + 1, PROPFIND_ALL_REQUEST);
- out_buffer.posn = 0;
- out_buffer.buffer = out_data;
+ if (!strcmp(ls->path, ls->dentry_name) && (ls->flags & IS_DIR)) {
+ remote_dir_exists[*parent] = 1;
+ return;
+ }
- in_buffer.size = 4096;
- in_data = xmalloc(in_buffer.size);
- in_buffer.posn = 0;
- in_buffer.buffer = in_data;
+ if (strlen(path) != 49)
+ return;
+ path += 8;
+ obj_hex = xmalloc(strlen(path));
+ strncpy(obj_hex, path, 2);
+ strcpy(obj_hex + 2, path + 3);
+ one_remote_object(obj_hex);
+ free(obj_hex);
+}
- dav_headers = curl_slist_append(dav_headers, "Depth: 1");
- dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
+static void process_ls_ref(struct remote_ls_ctx *ls)
+{
+ if (!strcmp(ls->path, ls->dentry_name) && (ls->dentry_flags & IS_DIR)) {
+ fprintf(stderr, " %s\n", ls->dentry_name);
+ return;
+ }
- slot = get_active_slot();
- slot->results = &results;
- curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
- curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
- curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
- curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
- curl_easy_setopt(slot->curl, CURLOPT_URL, url);
- curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
- curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
- curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
+ if (!(ls->dentry_flags & IS_DIR))
+ one_remote_ref(ls->dentry_name);
+}
- if (start_active_slot(slot)) {
- run_active_slot(slot);
- if (results.curl_result == CURLE_OK) {
- ctx.name = xcalloc(10, 1);
- ctx.len = 0;
- ctx.cdata = NULL;
- ctx.userFunc = handle_crawl_ref_ctx;
- ctx.userData = &dentry;
- XML_SetUserData(parser, &ctx);
- XML_SetElementHandler(parser, xml_start_tag,
- xml_end_tag);
- XML_SetCharacterDataHandler(parser, xml_cdata);
- result = XML_Parse(parser, in_buffer.buffer,
- in_buffer.posn, 1);
- free(ctx.name);
+static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
+{
+ struct remote_ls_ctx *ls = (struct remote_ls_ctx *)ctx->userData;
- if (result != XML_STATUS_OK) {
- fprintf(stderr, "XML error: %s\n",
- XML_ErrorString(
- XML_GetErrorCode(parser)));
+ if (tag_closed) {
+ if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && ls->dentry_name) {
+ if (ls->dentry_flags & IS_DIR) {
+ if (ls->flags & PROCESS_DIRS) {
+ ls->userFunc(ls);
+ }
+ if (strcmp(ls->dentry_name, ls->path) &&
+ ls->flags & RECURSIVE) {
+ remote_ls(ls->dentry_name,
+ ls->flags,
+ ls->userFunc,
+ ls->userData);
+ }
+ } else if (ls->flags & PROCESS_FILES) {
+ ls->userFunc(ls);
}
+ } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
+ ls->dentry_name = xmalloc(strlen(ctx->cdata) -
+ remote->path_len + 1);
+ strcpy(ls->dentry_name, ctx->cdata + remote->path_len);
+ } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
+ ls->dentry_flags |= IS_DIR;
}
- } else {
- fprintf(stderr, "Unable to start request\n");
+ } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
+ if (ls->dentry_name) {
+ free(ls->dentry_name);
+ }
+ ls->dentry_name = NULL;
+ ls->dentry_flags = 0;
}
-
- free(url);
- free(out_data);
- free(in_buffer.buffer);
- curl_slist_free_all(dav_headers);
}
-static void get_remote_object_list(unsigned char parent)
+static void remote_ls(const char *path, int flags,
+ void (*userFunc)(struct remote_ls_ctx *ls),
+ void *userData)
{
- char *url;
+ char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
struct active_request_slot *slot;
struct slot_results results;
struct buffer in_buffer;
@@ -1196,13 +1151,15 @@ static void get_remote_object_list(unsig
enum XML_Status result;
struct curl_slist *dav_headers = NULL;
struct xml_ctx ctx;
- char path[] = "/objects/XX/";
- static const char hex[] = "0123456789abcdef";
- unsigned int val = parent;
+ struct remote_ls_ctx ls;
+
+ ls.flags = flags;
+ ls.path = strdup(path);
+ ls.dentry_name = NULL;
+ ls.dentry_flags = 0;
+ ls.userData = userData;
+ ls.userFunc = userFunc;
- path[9] = hex[val >> 4];
- path[10] = hex[val & 0xf];
- url = xmalloc(strlen(remote->url) + strlen(path) + 1);
sprintf(url, "%s%s", remote->url, path);
out_buffer.size = strlen(PROPFIND_ALL_REQUEST);
@@ -1218,7 +1175,7 @@ static void get_remote_object_list(unsig
dav_headers = curl_slist_append(dav_headers, "Depth: 1");
dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
-
+
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
@@ -1234,11 +1191,11 @@ static void get_remote_object_list(unsig
if (start_active_slot(slot)) {
run_active_slot(slot);
if (results.curl_result == CURLE_OK) {
- remote_dir_exists[parent] = 1;
ctx.name = xcalloc(10, 1);
ctx.len = 0;
ctx.cdata = NULL;
- ctx.userFunc = handle_remote_object_list_ctx;
+ ctx.userFunc = handle_remote_ls_ctx;
+ ctx.userData = &ls;
XML_SetUserData(parser, &ctx);
XML_SetElementHandler(parser, xml_start_tag,
xml_end_tag);
@@ -1252,19 +1209,31 @@ static void get_remote_object_list(unsig
XML_ErrorString(
XML_GetErrorCode(parser)));
}
- } else {
- remote_dir_exists[parent] = 0;
}
} else {
- fprintf(stderr, "Unable to start request\n");
+ fprintf(stderr, "Unable to start PROPFIND request\n");
}
+ free(ls.path);
free(url);
free(out_data);
free(in_buffer.buffer);
curl_slist_free_all(dav_headers);
}
+static void get_remote_object_list(unsigned char parent)
+{
+ char path[] = "objects/XX/";
+ static const char hex[] = "0123456789abcdef";
+ unsigned int val = parent;
+
+ path[8] = hex[val >> 4];
+ path[9] = hex[val & 0xf];
+ remote_dir_exists[val] = 0;
+ remote_ls(path, (PROCESS_FILES | PROCESS_DIRS),
+ process_ls_object, &val);
+}
+
static int locking_available(void)
{
struct active_request_slot *slot;
@@ -1534,7 +1503,7 @@ static void get_local_heads(void)
static void get_dav_remote_heads(void)
{
remote_tail = &remote_refs;
- crawl_remote_refs("refs/");
+ remote_ls("refs/", (PROCESS_FILES | PROCESS_DIRS | RECURSIVE), process_ls_ref, NULL);
}
static int is_zero_sha1(const unsigned char *sha1)
--
1.2.4.g8e81-dirty
^ permalink raw reply related
* [PATCH 4/6] http-push: improve remote lock management
From: Nick Hengeveld @ 2006-03-11 4:18 UTC (permalink / raw)
To: git
Associate the remote locks with the remote repo, add a function to check
and refresh all current locks.
---
http-push.c | 149 ++++++++++++++++++++++++++++++-----------------------------
1 files changed, 76 insertions(+), 73 deletions(-)
fd1de0bf29e5e0fa63b851cb2195fbe05ebf80c2
diff --git a/http-push.c b/http-push.c
index 755bcb8..ece40da 100644
--- a/http-push.c
+++ b/http-push.c
@@ -80,10 +80,10 @@ struct repo
char *url;
int path_len;
struct packed_git *packs;
+ struct remote_lock *locks;
};
static struct repo *remote = NULL;
-static struct remote_lock *remote_locks = NULL;
enum transfer_state {
NEED_PUSH,
@@ -135,7 +135,6 @@ struct remote_lock
char *token;
time_t start_time;
long timeout;
- int active;
int refreshing;
struct remote_lock *next;
};
@@ -311,64 +310,69 @@ static void start_move(struct transfer_r
}
}
-static int refresh_lock(struct remote_lock *check_lock)
+static int refresh_lock(struct remote_lock *lock)
{
struct active_request_slot *slot;
struct slot_results results;
char *if_header;
char timeout_header[25];
struct curl_slist *dav_headers = NULL;
- struct remote_lock *lock;
- int time_remaining;
- time_t current_time;
+ int rc = 0;
- /* Refresh all active locks if they're close to expiring */
- for (lock = remote_locks; lock; lock = lock->next) {
- if (!lock->active)
- continue;
+ lock->refreshing = 1;
- current_time = time(NULL);
- time_remaining = lock->start_time + lock->timeout
- - current_time;
- if (time_remaining > LOCK_REFRESH)
- continue;
+ if_header = xmalloc(strlen(lock->token) + 25);
+ sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
+ sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
+ dav_headers = curl_slist_append(dav_headers, if_header);
+ dav_headers = curl_slist_append(dav_headers, timeout_header);
- lock->refreshing = 1;
+ slot = get_active_slot();
+ slot->results = &results;
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
+ curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
- if_header = xmalloc(strlen(lock->token) + 25);
- sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
- sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
- dav_headers = curl_slist_append(dav_headers, if_header);
- dav_headers = curl_slist_append(dav_headers, timeout_header);
+ if (start_active_slot(slot)) {
+ run_active_slot(slot);
+ if (results.curl_result != CURLE_OK) {
+ fprintf(stderr, "LOCK HTTP error %ld\n",
+ results.http_code);
+ } else {
+ lock->start_time = time(NULL);
+ rc = 1;
+ }
+ }
- slot = get_active_slot();
- slot->results = &results;
- curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
- curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
- curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
- curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
- curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
+ lock->refreshing = 0;
+ curl_slist_free_all(dav_headers);
+ free(if_header);
- if (start_active_slot(slot)) {
- run_active_slot(slot);
- if (results.curl_result != CURLE_OK) {
- fprintf(stderr, "Got HTTP error %ld\n", results.http_code);
- lock->active = 0;
- } else {
- lock->active = 1;
- lock->start_time = time(NULL);
+ return rc;
+}
+
+static void check_locks()
+{
+ struct remote_lock *lock = remote->locks;
+ time_t current_time = time(NULL);
+ int time_remaining;
+
+ while (lock) {
+ time_remaining = lock->start_time + lock->timeout -
+ current_time;
+ if (!lock->refreshing && time_remaining < LOCK_REFRESH) {
+ if (!refresh_lock(lock)) {
+ fprintf(stderr,
+ "Unable to refresh lock for %s\n",
+ lock->url);
+ aborted = 1;
+ return;
}
}
-
- lock->refreshing = 0;
- curl_slist_free_all(dav_headers);
- free(if_header);
+ lock = lock->next;
}
-
- if (check_lock)
- return check_lock->active;
- else
- return 0;
}
static void release_request(struct transfer_request *request)
@@ -396,7 +400,7 @@ static void finish_request(struct transf
request->slot = NULL;
/* Keep locks active */
- refresh_lock(request->lock);
+ check_locks();
if (request->headers != NULL)
curl_slist_free_all(request->headers);
@@ -483,6 +487,9 @@ static void add_request(struct object *o
struct transfer_request *request = request_queue_head;
struct packed_git *target;
+ /* Keep locks active */
+ check_locks();
+
/*
* Don't push the object if it's known to exist on the remote
* or is already in the request queue
@@ -893,7 +900,7 @@ static struct remote_lock *lock_remote(c
char *url;
char *ep;
char timeout_header[25];
- struct remote_lock *lock = remote_locks;
+ struct remote_lock *lock = NULL;
XML_Parser parser = XML_ParserCreate(NULL);
enum XML_Status result;
struct curl_slist *dav_headers = NULL;
@@ -902,18 +909,6 @@ static struct remote_lock *lock_remote(c
url = xmalloc(strlen(remote->url) + strlen(path) + 1);
sprintf(url, "%s%s", remote->url, path);
- /* Make sure the url is not already locked */
- while (lock && strcmp(lock->url, url)) {
- lock = lock->next;
- }
- if (lock) {
- free(url);
- if (refresh_lock(lock))
- return lock;
- else
- return NULL;
- }
-
/* Make sure leading directories exist for the remote ref */
ep = strchr(url + strlen(remote->url) + 11, '/');
while (ep) {
@@ -971,10 +966,7 @@ static struct remote_lock *lock_remote(c
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
lock = xcalloc(1, sizeof(*lock));
- lock->owner = NULL;
- lock->token = NULL;
lock->timeout = -1;
- lock->refreshing = 0;
if (start_active_slot(slot)) {
run_active_slot(slot);
@@ -1016,10 +1008,9 @@ static struct remote_lock *lock_remote(c
lock = NULL;
} else {
lock->url = url;
- lock->active = 1;
lock->start_time = time(NULL);
- lock->next = remote_locks;
- remote_locks = lock;
+ lock->next = remote->locks;
+ remote->locks = lock;
}
return lock;
@@ -1029,6 +1020,7 @@ static int unlock_remote(struct remote_l
{
struct active_request_slot *slot;
struct slot_results results;
+ struct remote_lock *prev = remote->locks;
char *lock_token_header;
struct curl_slist *dav_headers = NULL;
int rc = 0;
@@ -1050,16 +1042,29 @@ static int unlock_remote(struct remote_l
if (results.curl_result == CURLE_OK)
rc = 1;
else
- fprintf(stderr, "Got HTTP error %ld\n",
+ fprintf(stderr, "UNLOCK HTTP error %ld\n",
results.http_code);
} else {
- fprintf(stderr, "Unable to start request\n");
+ fprintf(stderr, "Unable to start UNLOCK request\n");
}
curl_slist_free_all(dav_headers);
free(lock_token_header);
- lock->active = 0;
+ if (remote->locks == lock) {
+ remote->locks = lock->next;
+ } else {
+ while (prev && prev->next != lock)
+ prev = prev->next;
+ if (prev)
+ prev->next = prev->next->next;
+ }
+
+ if (lock->owner != NULL)
+ free(lock->owner);
+ free(lock->url);
+ free(lock->token);
+ free(lock);
return rc;
}
@@ -1597,7 +1602,7 @@ int main(int argc, char **argv)
struct transfer_request *next_request;
int nr_refspec = 0;
char **refspec = NULL;
- struct remote_lock *ref_lock;
+ struct remote_lock *ref_lock = NULL;
struct rev_info revs;
int rc = 0;
int i;
@@ -1605,10 +1610,7 @@ int main(int argc, char **argv)
setup_git_directory();
setup_ident();
- remote = xmalloc(sizeof(*remote));
- remote->url = NULL;
- remote->path_len = 0;
- remote->packs = NULL;
+ remote = xcalloc(sizeof(*remote), 1);
argv++;
for (i = 1; i < argc; i++, argv++) {
@@ -1787,6 +1789,7 @@ int main(int argc, char **argv)
if (!rc)
fprintf(stderr, " done\n");
unlock_remote(ref_lock);
+ check_locks();
}
cleanup:
--
1.2.4.g8e81-dirty
^ permalink raw reply related
* [PATCH 6/6] http-push: cleanup
From: Nick Hengeveld @ 2006-03-11 4:18 UTC (permalink / raw)
To: git
More consistent usage string, condense push output, remove extra slashes
in URLs, fix unused variables, include HTTP method name in failure
messages.
---
http-push.c | 51 ++++++++++++++++++++++++++++++---------------------
1 files changed, 30 insertions(+), 21 deletions(-)
84bd077e6aa433485124d9dd433ef3d7b674e5ea
diff --git a/http-push.c b/http-push.c
index 65c6664..181a0d4 100644
--- a/http-push.c
+++ b/http-push.c
@@ -11,7 +11,7 @@
#include <expat.h>
static const char http_push_usage[] =
-"git-http-push [--complete] [--force] [--verbose] <url> <ref> [<ref>...]\n";
+"git-http-push [--all] [--force] [--verbose] <remote> [<head>...]\n";
#ifndef XML_STATUS_OK
enum XML_Status {
@@ -707,8 +707,9 @@ static void finish_request(struct transf
}
} else if (request->state == RUN_MOVE) {
if (request->curl_result == CURLE_OK) {
- fprintf(stderr, " sent %s\n",
- sha1_to_hex(request->obj->sha1));
+ if (push_verbosely)
+ fprintf(stderr, " sent %s\n",
+ sha1_to_hex(request->obj->sha1));
request->obj->flags |= REMOTE;
release_request(request);
} else {
@@ -848,7 +849,7 @@ static void add_fetch_request(struct obj
step_active_slots();
}
-static void add_send_request(struct object *obj, struct remote_lock *lock)
+static int add_send_request(struct object *obj, struct remote_lock *lock)
{
struct transfer_request *request = request_queue_head;
struct packed_git *target;
@@ -863,11 +864,11 @@ static void add_send_request(struct obje
if (remote_dir_exists[obj->sha1[0]] == -1)
get_remote_object_list(obj->sha1[0]);
if (obj->flags & (REMOTE | PUSHING))
- return;
+ return 0;
target = find_sha1_pack(obj->sha1, remote->packs);
if (target) {
obj->flags |= REMOTE;
- return;
+ return 0;
}
obj->flags |= PUSHING;
@@ -884,6 +885,8 @@ static void add_send_request(struct obje
fill_active_slots();
step_active_slots();
+
+ return 1;
}
static int fetch_index(unsigned char *sha1)
@@ -901,8 +904,8 @@ static int fetch_index(unsigned char *sh
struct slot_results results;
/* Don't use the index if the pack isn't there */
- url = xmalloc(strlen(remote->url) + 65);
- sprintf(url, "%s/objects/pack/pack-%s.pack", remote->url, hex);
+ url = xmalloc(strlen(remote->url) + 64);
+ sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
@@ -924,7 +927,7 @@ static int fetch_index(unsigned char *sh
if (push_verbosely)
fprintf(stderr, "Getting index for pack %s\n", hex);
- sprintf(url, "%s/objects/pack/pack-%s.idx", remote->url, hex);
+ sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex);
filename = sha1_pack_index_name(sha1);
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
@@ -1009,8 +1012,8 @@ static int fetch_indices(void)
if (push_verbosely)
fprintf(stderr, "Getting pack list\n");
- url = xmalloc(strlen(remote->url) + 21);
- sprintf(url, "%s/objects/info/packs", remote->url);
+ url = xmalloc(strlen(remote->url) + 20);
+ sprintf(url, "%sobjects/info/packs", remote->url);
slot = get_active_slot();
slot->results = &results;
@@ -1298,7 +1301,7 @@ static struct remote_lock *lock_remote(c
return NULL;
}
} else {
- fprintf(stderr, "Unable to start request\n");
+ fprintf(stderr, "Unable to start MKCOL request\n");
free(url);
return NULL;
}
@@ -1359,7 +1362,7 @@ static struct remote_lock *lock_remote(c
}
}
} else {
- fprintf(stderr, "Unable to start request\n");
+ fprintf(stderr, "Unable to start LOCK request\n");
}
curl_slist_free_all(dav_headers);
@@ -1673,7 +1676,7 @@ static int locking_available(void)
}
}
} else {
- fprintf(stderr, "Unable to start request\n");
+ fprintf(stderr, "Unable to start PROPFIND request\n");
}
free(out_data);
@@ -1734,16 +1737,17 @@ static struct object_list **process_tree
return p;
}
-static void get_delta(struct rev_info *revs, struct remote_lock *lock)
+static int get_delta(struct rev_info *revs, struct remote_lock *lock)
{
struct commit *commit;
struct object_list **p = &objects, *pending;
+ int count = 0;
while ((commit = get_revision(revs)) != NULL) {
p = process_tree(commit->tree, p, NULL, "");
commit->object.flags |= LOCAL;
if (!(commit->object.flags & UNINTERESTING))
- add_send_request(&commit->object, lock);
+ count += add_send_request(&commit->object, lock);
}
for (pending = revs->pending_objects; pending; pending = pending->next) {
@@ -1770,9 +1774,11 @@ static void get_delta(struct rev_info *r
while (objects) {
if (!(objects->item->flags & UNINTERESTING))
- add_send_request(objects->item, lock);
+ count += add_send_request(objects->item, lock);
objects = objects->next;
}
+
+ return count;
}
static int update_remote(unsigned char *sha1, struct remote_lock *lock)
@@ -2106,6 +2112,7 @@ int main(int argc, char **argv)
struct remote_lock *ref_lock = NULL;
struct remote_lock *info_ref_lock = NULL;
struct rev_info revs;
+ int objects_to_send;
int rc = 0;
int i;
@@ -2197,7 +2204,6 @@ int main(int argc, char **argv)
return 0;
}
- int ret = 0;
int new_refs = 0;
struct ref *ref;
for (ref = remote_refs; ref; ref = ref->next) {
@@ -2229,14 +2235,14 @@ int main(int argc, char **argv)
"need to pull first?",
ref->name,
ref->peer_ref->name);
- ret = -2;
+ rc = -2;
continue;
}
}
memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
if (is_zero_sha1(ref->new_sha1)) {
error("cannot happen anymore");
- ret = -3;
+ rc = -3;
continue;
}
new_refs++;
@@ -2283,12 +2289,15 @@ int main(int argc, char **argv)
pushing = 0;
prepare_revision_walk(&revs);
mark_edges_uninteresting(revs.commits);
- get_delta(&revs, ref_lock);
+ objects_to_send = get_delta(&revs, ref_lock);
finish_all_active_slots();
/* Push missing objects to remote, this would be a
convenient time to pack them first if appropriate. */
pushing = 1;
+ if (objects_to_send)
+ fprintf(stderr, " sending %d objects\n",
+ objects_to_send);
fill_active_slots();
finish_all_active_slots();
--
1.2.4.g8e81-dirty
^ permalink raw reply related
* Re: Some more cvsimport
From: Matthias Urlichs @ 2006-03-11 6:34 UTC (permalink / raw)
To: git
In-Reply-To: <440E9AA8.2020605@asianetindia.com>
Hi, Rajkumar S wrote:
> When I normally do cvsimport, the releng_1
> tree gets updated automatically, but if I have checked out the releng_1
> branch in my local git repository when cvsimport happens the files do not
> get updated.
Don't Do That.
I just removed the "update checked-out tree" logic because it has too many
corner cases.
I could conceivably add a check for HEAD pointing to the CVS branch I'm
just checking out, but on second thought I'd rather wait for the
refs/remotes/ work to show up, and then simply s/heads/remotes/g. ;-)
--
Matthias Urlichs
^ permalink raw reply
* Re: bug?: stgit creates (unneccessary?) conflicts when pulling
From: Junio C Hamano @ 2006-03-11 6:46 UTC (permalink / raw)
To: Catalin Marinas; +Cc: Junio C Hamano, git, Shawn Pearce
In-Reply-To: <b0943d9e0603100313l37f67f62h@mail.gmail.com>
"Catalin Marinas" <catalin.marinas@gmail.com> writes:
> On 09/03/06, Junio C Hamano <junkio@cox.net> wrote:
>
>> Yup, it was originally done to improve the performance of
>> resolve merge strategy, but I am glad somebody else has found
>> use for it.
>
> Actually, I asked for it about 6 months ago:
>
> http://marc.theaimsgroup.com/?l=git&m=112677889118711&w=2
>
> and I got the reply from you :-):
>
> http://marc.theaimsgroup.com/?l=git&m=112690084826630&w=2
>
> Anyway, it's good we have it...
I had this one in mind:
http://marc.theaimsgroup.com/?t=113874460800001&r=1&w=2
Specifically, this message:
http://marc.theaimsgroup.com/?l=git&m=113874886615202&w=2
It seems that this has been an recurring issue.
^ permalink raw reply
* Re: Some more cvsimport
From: Junio C Hamano @ 2006-03-11 7:00 UTC (permalink / raw)
To: Rajkumar S; +Cc: git, Matthias Urlichs
In-Reply-To: <pan.2006.03.11.06.34.26.200002@smurf.noris.de>
Matthias Urlichs <smurf@smurf.noris.de> writes:
> Hi, Rajkumar S wrote:
>
>> When I normally do cvsimport, the releng_1
>> tree gets updated automatically, but if I have checked out the releng_1
>> branch in my local git repository when cvsimport happens the files do not
>> get updated.
>
> Don't Do That.
I tend to agree with this.
Think of foreign SCM imports, especially the ones that do not
use working tree files, just like tracking foreign branch heads
using "git fetch". You do not fetch into the current branch,
nor you check out and do your work tracking branch. You use
them to keep track of other people's work, and if you want to
use it you pull that into your branch, typically but not
necessarily "master".
^ permalink raw reply
* Re: annotate.perl triggers rpm bug
From: Junio C Hamano @ 2006-03-11 7:11 UTC (permalink / raw)
To: sean; +Cc: git
In-Reply-To: <BAYC1-PASMTP0815EFABBF5266FB641C65AEED0@CEZ.ICE>
sean <seanlkml@sympatico.ca> writes:
> .... RPM automatically creates a dependency for any
> perl "use" lines, and the above commit fools it into creating a false
> dependecy...
Sheesh -- broken packaging.
> diff --git a/git-annotate.perl b/git-annotate.perl
> index feea0a2..6805b8b 100755
> --- a/git-annotate.perl
> +++ b/git-annotate.perl
> @@ -20,7 +20,7 @@ sub usage() {
> -r, --rename
> Follow renames (Defaults on).
> -S, --rev-file revs-file
> - use revs from revs-file instead of calling git-rev-list
> + uses revs from revs-file instead of calling git-rev-list
> -h, --help
> This message.
> ';
How about upcasing the word like other lines?
^ permalink raw reply
* Re: annotate.perl triggers rpm bug
From: sean @ 2006-03-11 7:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v64mlxxq2.fsf@assigned-by-dhcp.cox.net>
On Fri, 10 Mar 2006 23:11:01 -0800
Junio C Hamano <junkio@cox.net> wrote:
> Sheesh -- broken packaging.
Yeah, not rpm's proudest moment.
> How about upcasing the word like other lines?
That seems to fix the dependency problem too and makes a little
more sense.
Sean
diff --git a/git-annotate.perl b/git-annotate.perl
index feea0a2..9df72a1 100755
--- a/git-annotate.perl
+++ b/git-annotate.perl
@@ -20,7 +20,7 @@ sub usage() {
-r, --rename
Follow renames (Defaults on).
-S, --rev-file revs-file
- use revs from revs-file instead of calling git-rev-list
+ Use revs from revs-file instead of calling git-rev-list
-h, --help
This message.
';
^ permalink raw reply related
* [PATCH] imap-send: cleanup execl() call to use NULL sentinel instead of 0
From: Marco Roeland @ 2006-03-11 8:55 UTC (permalink / raw)
To: Mike McCormack; +Cc: git
Some versions of gcc check that calls to the exec() family have the proper
sentinel for variadic calls. This should be (char *) NULL according to the
man page. Although for all other purposes the 0 is equivalent, gcc
nevertheless does emit a warning for 0 and not for NULL. This also makes the
usage consistent throughout git.
The whitespace in function calls throughout imap-send.c has its own style,
so I left it that way.
---
imap-send.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
db1a0875cbc28970208e7a2fbb93d680d8ffe572
diff --git a/imap-send.c b/imap-send.c
index fddaac0..203284d 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -945,7 +945,7 @@ imap_open_store( imap_server_conf_t *srv
_exit( 127 );
close( a[0] );
close( a[1] );
- execl( "/bin/sh", "sh", "-c", srvc->tunnel, 0 );
+ execl( "/bin/sh", "sh", "-c", srvc->tunnel, NULL );
_exit( 127 );
}
--
1.2.4.ge29f
Marco Roeland
^ permalink raw reply related
* [PATCH 4/4] Add quick reference
From: Jonas Fonseca @ 2006-03-11 13:12 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
In-Reply-To: <20060310144835.GE7920@diku.dk>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
---
This renames quick-reference.txt to cg-ref.txt to address the
cg-ref.pdf issue, makes the script more robust by using printf for
alignment, and improves the reference itself a bit.
Documentation/Makefile | 9 ++-
Documentation/asciidoc.conf | 4 +
Documentation/cg-ref.txt | 116 ++++++++++++++++++++++++++++++++++++
Documentation/make-cg-ref-asciidoc | 70 ++++++++++++++++++++++
4 files changed, 196 insertions(+), 3 deletions(-)
diff --git a/Documentation/Makefile b/Documentation/Makefile
index d316a14..b38fc4d 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -4,14 +4,14 @@ CG_SRC=$(filter-out $(CG_IGNORE), $(wild
PACKAGE=cogito
MAN1_TXT=$(patsubst ../cg%,cg%.1.txt,$(CG_SRC))
-MAN7_TXT=$(PACKAGE).7.txt
+MAN7_TXT=$(PACKAGE).7.txt cg-ref.7.txt
-DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) introduction.html
+DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) cg-ref.html introduction.html
DOC_MAN1=$(patsubst %.txt,%,$(MAN1_TXT))
DOC_MAN7=$(patsubst %.txt,%,$(MAN7_TXT))
-DOC_PDF=$(patsubst %.txt,%.pdf,$(MAN1_TXT) $(MAN7_TXT)) introduction.pdf
+DOC_PDF=$(patsubst %.txt,%.pdf,$(MAN1_TXT) $(MAN7_TXT)) cg-ref.pdf introduction.pdf
prefix=$(HOME)
bin=$(prefix)/bin
@@ -100,6 +100,9 @@ introduction.xml: ../README
$(PACKAGE).7.txt : make-$(PACKAGE)-asciidoc
./make-$(PACKAGE)-asciidoc > $@
+cg-ref.7.txt : cg-ref.txt make-cg-ref-asciidoc
+ CGPACKAGE=$(PACKAGE) ./make-cg-ref-asciidoc $< > $@
+
# It seems that cg%.txt won't match this so use an explicit rule
cg.1.txt : ../cg make-cg-asciidoc
CGPACKAGE=$(PACKAGE) ./make-cg-asciidoc $< > $@
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index baefb2f..69f1646 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -19,3 +19,7 @@ ifdef::backend-xhtml11[]
[gitlink-inlinemacro]
<a href="{target}.html">{target}{0?({0})}</a>
endif::backend-xhtml11[]
+
+[attributes]
+# Five non breaking spaces used for option indentation in the quick reference
+cg-refopt=     
diff --git a/Documentation/cg-ref.txt b/Documentation/cg-ref.txt
new file mode 100644
index 0000000..ab2321b
--- /dev/null
+++ b/Documentation/cg-ref.txt
@@ -0,0 +1,116 @@
+Cogito Quick Reference
+======================
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Getting help:
+------------------------------------------------------------------------------
+*cg help* 'command' Show help for a command
+*cg* 'command' -h Show usage summary for a command
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Repository creation:
+------------------------------------------------------------------------------
+*cg init* Create a repository in the current directory
+*cg clone* 'url' Clone a remote repository into a subdirectory
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+File operations:
+------------------------------------------------------------------------------
+*cg add* 'file' Add file to the working tree
+*cg add* -r 'directory' Recursively add files in directory
+*cg rm* 'file' Remove file or directory from the working tree
+*cg rm* -r 'directory' Recursively remove files in directory
+{cg-refopt} -f Delete file from disk
+*cg mv* 'file' 'destination' Move file or directory to new location
+{cg-refopt} -f Overwrite existing destination files
+*cg restore* 'file' Restore file
+{cg-refopt} -r 'revision' Bring back file from revision (and add it)
+{cg-refopt} -f Overwrite uncommitted changes
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Working tree:
+------------------------------------------------------------------------------
+*cg status* '[file]' Show branches and status of the working tree
+*cg reset* Reset the working tree
+*cg clean* Clean unknown files from the working tree
+*cg commit* '[file]' Commit the working tree
+{cg-refopt} -m 'message' Append message to commit log
+*cg admin-uncommit* Undo commit
+*cg seek* 'revision' Temporarily switch the working tree
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Examining History:
+------------------------------------------------------------------------------
+*cg log* '[file]' View commit log
+{cg-refopt} -r 'revision' Limit to revision range
+{cg-refopt} -f List affected files
+{cg-refopt} -s Summarize commits to one line
+*cg diff* '[file]' Show diff of changes
+{cg-refopt} -r 'revision' Diff revision instead of working tree
+{cg-refopt} -p Diff against parent
+{cg-refopt} -s Show diff stat
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Remote branches:
+------------------------------------------------------------------------------
+*cg fetch* '[branch]' Fetch changes from a remote branch
+*cg update* '[branch]' Fetch and merge changes from a remote branch
+*cg push* '[branch]' Push changes to a remote branch
+*cg branch-ls* List remote branches
+*cg branch-add* 'branch' 'url' Add remote branch
+*cg branch-chg* 'branch' 'url' Change URL of existing branch
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Local branches:
+------------------------------------------------------------------------------
+*cg merge* 'branch' Merge changes from branch
+*cg switch* 'branch' Switch the working tree to branch
+{cg-refopt} -r 'revision' Create branch from revision
+{cg-refopt} -f Overwrite existing branch
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Exporting and importing:
+------------------------------------------------------------------------------
+*cg patch* < 'file' Apply patch from stdin
+*cg mkpatch* Format a patch with log message and diffstat
+{cg-refopt} -r 'revision' Limit to revision range
+*cg export* 'directory' Export snapshot to directory
+*cg export* 'file.tar.gz' Export snapshot to tar file
+{cg-refopt} -r 'revision' Base snapshot on revision
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Tags:
+------------------------------------------------------------------------------
+*cg tag* 'name' 'revision' Create tag for a given revision
+{cg-refopt} -s Sign tag with your private key using GPG
+*cg tag-ls* Show name and revision for all tags
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+File status flags:
+------------------------------------------------------------------------------
+`?` unknown File is not under revision control
+`A` added File has been added
+`D` deleted File has been deleted
+`!` disappeared File is not in the working tree
+`M` modified File has been touched or modified
+`m` modified (while merging) File was modified prior to the merge
+------------------------------------------------------------------------------
diff --git a/Documentation/make-cg-ref-asciidoc b/Documentation/make-cg-ref-asciidoc
new file mode 100755
index 0000000..960e711
--- /dev/null
+++ b/Documentation/make-cg-ref-asciidoc
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+#
+# Generate asciidoc manpage markup from Cogito quick reference file.
+# Copyright (c) Jonas Fonseca, 2006
+#
+# Takes the path to the reference file. Prints the manpage to stdout.
+
+PACKAGE=${CGPACKAGE:-cogito}
+
+ref=$1
+
+cat <<__END__
+cg-ref(7)
+=========
+
+NAME
+----
+cg-ref - Cogito quick reference
+
+SYNOPSIS
+--------
+A list of frequently used commands grouped with related commands.
+
+DESCRIPTION
+-----------
+
+__END__
+
+sed '
+ 0,/^$/d
+ /^`---/d
+ /frame="none"/,1d
+ s/\\$//
+ s/[*]\([^*]*\)[*]/\1/g
+ s/[`]\([^`]*\)[`]/\1/g
+ s/['\'']\([^'\'']*\)['\'']/\1/g
+' < "$ref" | \
+while read line; do
+ col1=$(echo "$line" | cut -f 1)
+ case "$line" in
+ *":")
+ echo "$line"
+ echo "$line" | sed "s/[^~]/~/g"
+ echo
+ echo "[verse]"
+ continue
+ ;;
+ "-----"*|"")
+ echo "$line" | sed 's/-/./g'
+ continue
+ ;;
+ "{cg-refopt}"*)
+ col1=$(echo "$col1" | sed 's/.*cg-refopt}/ /')
+ ;;
+ esac
+ col2=$(echo "$line" | sed 's/.*[ ]\+//')
+ printf "%-30s %s\n" "$col1" "$col2"
+done
+
+cat << __END__
+
+COPYRIGHT
+---------
+Copyright (C) Jonas Fonseca, 2006.
+
+SEE ALSO
+--------
+gitlink:cg-ref[7] is part of gitlink:${PACKAGE}[7],
+a toolkit for managing gitlink:git[7] trees.
+__END__
--
Jonas Fonseca
^ permalink raw reply related
* [PATCH] cg-export: document the -r option
From: Jonas Fonseca @ 2006-03-11 13:13 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
---
commit 4ac3822d222d8562a4cf4ac1edac1e2d60d40535
tree da406621cea613a71e3d46ce71bd629ce5d709d4
parent 129519d0f337f83699bad485dec105a6528961a2
author Jonas Fonseca <fonseca@diku.dk> Sat, 11 Mar 2006 13:56:42 +0100
committer Jonas Fonseca <fonseca@antimatter.localdomain> Sat, 11 Mar 2006 13:56:42 +0100
cg-export | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/cg-export b/cg-export
index 7acc1a0..cf9f0fd 100755
--- a/cg-export
+++ b/cg-export
@@ -9,6 +9,11 @@
# The destination can be either a `.tar`, `.tar.gz`, `.tar.bz2` or `.tgz`
# for generating a tarball. Other destination specifiers are assumed
# to be directory names, and the tree is exported to the given directory.
+#
+# OPTIONS
+# -------
+# -r TREE_ID:: Specify the tree version to export
+# Base the export on the given tree.
USAGE="cg-export [-r TREE_ID] DESTFILE"
_git_requires_root=1
--
Jonas Fonseca
^ permalink raw reply related
* Re: [PATCH] imap-send: cleanup execl() call to use NULL sentinel instead of 0
From: Morten Welinder @ 2006-03-11 14:01 UTC (permalink / raw)
To: Marco Roeland; +Cc: Mike McCormack, git
In-Reply-To: <20060311085550.GA32089@fiberbit.xs4all.nl>
If you're going to fix that, you should use (char *)NULL or
(char *)0, just in case you end up on a machine where
NULL doesn't a pointer type.
(Yup, NULL can be a null pointer without having pointer type.)
M.
^ permalink raw reply
* git-diff-tree -M performance regression in 'next'
From: Fredrik Kuivinen @ 2006-03-11 17:28 UTC (permalink / raw)
To: git; +Cc: junkio
Hi,
I added some time logging code to git-merge-recursive to see exactly
what we spend all the time on in merges which involves many changes,
such as a merge of a slightly modified v2.6.12 and an unmodified
v2.6.15.
I turned out that the rename detection took almost 10 minutes on my
machine. More specifically,
git-diff-tree -r -M --diff-filter=R v2.6.12 v2.6.14
takes ~9 minutes with the current 'next'.
With 65416758cd83772f2f3c69f1bd1f501608e64745, which uses the delta
code to compute the similarity measure, the above git-diff-tree
invocation takes 1.50 minutes.
- Fredrik
^ permalink raw reply
* [PATCH] Trivial warning fix for imap-send.c
From: Art Haas @ 2006-03-11 19:29 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
Hi.
After my 'git' repo this morning and building I noticed a GCC warning
about a missing sentinel in this file. A scan of the libc docs says
that execl() needs to end with a terminating NULL, as the miniscule
change below does, and recompliation with GCC removed the warning.
Art Haas
Signed-off-by: Art Haas <ahaas@airmail.net>
diff --git a/imap-send.c b/imap-send.c
index fddaac0..203284d 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -945,7 +945,7 @@ imap_open_store( imap_server_conf_t *srv
_exit( 127 );
close( a[0] );
close( a[1] );
- execl( "/bin/sh", "sh", "-c", srvc->tunnel, 0 );
+ execl( "/bin/sh", "sh", "-c", srvc->tunnel, NULL );
_exit( 127 );
}
--
Man once surrendering his reason, has no remaining guard against absurdities
the most monstrous, and like a ship without rudder, is the sport of every wind.
-Thomas Jefferson to James Smith, 1822
^ permalink raw reply related
* Re: [PATCH] imap-send: cleanup execl() call to use NULL sentinel instead of 0
From: Marco Roeland @ 2006-03-11 20:30 UTC (permalink / raw)
To: Morten Welinder; +Cc: Mike McCormack, git
In-Reply-To: <118833cc0603110601x6ac9b2b6kaa0277981c6dd44b@mail.gmail.com>
On Saturday March 11th 2006 Morten Welinder wrote:
> If you're going to fix that, you should use (char *)NULL or
> (char *)0, just in case you end up on a machine where
> NULL doesn't a pointer type.
>
> (Yup, NULL can be a null pointer without having pointer type.)
For gcc NULL is specifically always guaranteed to be a valid sentinel.
And it was basically just about fixing the gcc warning, no pedantics
intended! All other uses within git for the exec() family also use plain
uncast NULL, which looks better anyway.
Strictly speaking you're probably right, but there's a chance that this
will generate warnings on other compilers.
And if you should use a compiler with a weird notion of NULL, you're
probably better off switching compilers immediately. ;-)
--
Marco Roeland
^ permalink raw reply
* Re: git-diff-tree -M performance regression in 'next'
From: Junio C Hamano @ 2006-03-12 3:10 UTC (permalink / raw)
To: Fredrik Kuivinen; +Cc: git, junkio
In-Reply-To: <20060311172818.GB32609@c165.ib.student.liu.se>
Fredrik Kuivinen <freku045@student.liu.se> writes:
> I turned out that the rename detection took almost 10 minutes on my
> machine.
Yes, that is one of the reasons why it still is in "next", not
in "master".
The rename-detector change was done primarily to work around the
correctness problem the finer-grained delta changes would have
introduced. The new delta code would have produced far more
copies from the source than the current xdelta code, but the
nature of the new copies it would have found was quite different
from what we would usually call "file being renamed". Now we
decided to shelve the finer-grained delta code for now, I do not
see a pressing reason to have the experimental rename detector
graduate to "master" until we resolve its performance issues.
^ permalink raw reply
* Re: [PATCH] Trivial warning fix for imap-send.c
From: Mark Wooding @ 2006-03-12 10:44 UTC (permalink / raw)
To: git
In-Reply-To: <20060311192954.GQ16135@artsapartment.org>
"Art Haas" <ahaas@airmail.net> wrote:
> --- a/imap-send.c
> +++ b/imap-send.c
> @@ -945,7 +945,7 @@ imap_open_store( imap_server_conf_t *srv
> _exit( 127 );
> close( a[0] );
> close( a[1] );
> - execl( "/bin/sh", "sh", "-c", srvc->tunnel, 0 );
> + execl( "/bin/sh", "sh", "-c", srvc->tunnel, NULL );
> _exit( 127 );
> }
This is not the right fix. NULL can be simply a #define for 0 (see
6.3.2.3#3 and 7.17). You need to write (char *)0 or (char *)NULL. I
prefer to avoid the macro NULL entirely, since its misleading behaviour
is precisely what got us into this mess.
-- [mdw]
^ permalink raw reply
* [PATCH] imap-send: Add missing #include for macosx
From: Johannes Schindelin @ 2006-03-12 10:55 UTC (permalink / raw)
To: git, junkio
There is a compile error without that.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
imap-send.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
4f24a9d215bca31f40d5b994f59fff012e14086f
diff --git a/imap-send.c b/imap-send.c
index fddaac0..c2fd0fd 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -28,6 +28,7 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
+#include <sys/socket.h>
#include <netdb.h>
typedef struct store_conf {
--
1.2.0.gaa33-dirty
^ permalink raw reply related
* Re: [PATCH] Trivial warning fix for imap-send.c
From: Junio C Hamano @ 2006-03-12 11:27 UTC (permalink / raw)
To: Mark Wooding; +Cc: git
In-Reply-To: <slrne17urp.fr9.mdw@metalzone.distorted.org.uk>
Mark Wooding <mdw@distorted.org.uk> writes:
> This is not the right fix. NULL can be simply a #define for 0 (see
> 6.3.2.3#3 and 7.17). You need to write (char *)0 or (char *)NULL. I
> prefer to avoid the macro NULL entirely, since its misleading behaviour
> is precisely what got us into this mess.
Patches welcome. We have about 15 or so such instances.
$ git grep -n -H 'execl[_a-z]*(' '*.c'
cat-file.c:139: return execl_git_cmd("ls-tree", argv[2], NULL);
connect.c:547: execlp(git_proxy_command, git_proxy_command, host, port, NULL);
connect.c:646: execlp(ssh, ssh_basename, host, command, NULL);
connect.c:654: execlp("sh", "sh", "-c", command, NULL);
daemon.c:263: execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL);
exec_cmd.c:97:int execl_git_cmd(const char *cmd,...)
fetch-clone.c:32: execl_git_cmd("index-pack", "-o", idx, pack_tmp_name, NULL);
fetch-clone.c:109: execl_git_cmd("unpack-objects", quiet ? "-q" : NULL, NULL);
git.c:256: execlp("man", "man", page, NULL);
imap-send.c:948: execl( "/bin/sh", "sh", "-c", srvc->tunnel, NULL );
merge-index.c:18: execlp(pgm, arguments[0],
pager.c:14: execlp(prog, prog, NULL);
rsh.c:106: execlp(ssh, ssh_basename, host, command, NULL);
upload-pack.c:92: execl_git_cmd("pack-objects", "--stdout", NULL);
^ permalink raw reply
* Re: git-diff-tree -M performance regression in 'next'
From: Junio C Hamano @ 2006-03-12 12:28 UTC (permalink / raw)
To: Fredrik Kuivinen; +Cc: git
In-Reply-To: <20060311172818.GB32609@c165.ib.student.liu.se>
Fredrik Kuivinen <freku045@student.liu.se> writes:
> I turned out that the rename detection took almost 10 minutes on my
> machine. More specifically,
>
> git-diff-tree -r -M --diff-filter=R v2.6.12 v2.6.14
>
> takes ~9 minutes with the current 'next'.
I have some updates to "next" tonight.
On my otherwise idle Duron 750 with slow disks, I am getting
something like these:
0.99.9m : 130m virtual, 40m resident, (0major+14205minor)
67.62user 0.08system 1:15.95elapsed
master : 130m virtual, 40m resident, (0major+12510minor)
66.06user 0.07system 1:10.95elapsed
"next" : 150m virtual, 65m resident, (0major+49858minor)
51.41user 0.45system 0.57.55elapsed
The result will _not_ exactly match, because the similarity
estimation algorithms are different.
Judging the differences objectively is a bit hard, but my
impression is that the "next" one tends to find more sensible
renames. To name a few:
* Documentation/dvb/README.dibusb from v2.6.12 seems pretty
similar to Documentation/dvb/README.dvb-usb from v2.6.14, and
"next" finds them, but "master" does not.
* "master" says arch/arm/configs/omnimeter_defconfig was
copy-edited to produce arch/arm/configs/collie_defconfig; The
diff output shows ~350 new lines and ~270 deleted lines, while
these files are 800-900 lines long; "next" rejects them. I
think this is a border-line case.
* "next" finds Kconfig and Makefile in arch/arm/mach-omap-1/ are
derived from arch/arm/mach-omap/; manual inspection of these
files makes me feel that decision is sensible. "master" does
not find them.
* Same thing for config.c in arch/m68knommu/platform/68VZ328/;
found to be derived from arch/m68knommu/platform/68VZ328/de2/ by
"next" but not by "master".
* Other examples "next" finds but "master" misses include:
arch/um/kernel/process.c arch/um/os-Linux/start_up.c
arch/um/kernel/tt/unmap.c arch/um/sys-x86_64/unmap.c
drivers/ide/cris/ide-v10.c drivers/ide/cris/ide-cris.c
include/asm-ppc/cputime.h include/asm-xtensa/cputime.h
include/asm-ppc64/ioctl.h include/asm-xtensa/ioctl.h
include/asm-ppc64/ioctls.h include/asm-xtensa/ioctls.h
include/asm-ppc64/mman.h include/asm-xtensa/mman.h
include/asm-ppc64/poll.h include/asm-xtensa/poll.h
include/asm-ppc64/shmbuf.h include/asm-xtensa/shmbuf.h
include/asm-ppc64/socket.h include/asm-xtensa/socket.h
include/asm-ppc64/termbits.h include/asm-xtensa/termbits.h
* The "next" one is not perfect. There are some quite bad
choices made by it:
include/asm-ppc64/timex.h include/asm-powerpc/bugs.h
include/asm-ppc64/iSeries/LparData.h include/linux/i2c-isa.h
^ permalink raw reply
* [PATCH] Use explicit pointers for execl...() sentinels.
From: Mark Wooding @ 2006-03-12 13:59 UTC (permalink / raw)
To: git
In-Reply-To: <7v7j6zgaxx.fsf@assigned-by-dhcp.cox.net>
A terminator of `0' (or `NULL', which might well expand to `0') gets
passed as type `int' in the absence of argument type declarations (which
is the case for execl...(), since it uses varargs). Argument passing
conventions may differ between `int' and `char *' if, say, `int' is 32
bits and pointers a 64; and there's no particular guarantee that a null
pointer has all-bits-zero anyway.
Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
---
Junio C Hamano <junkio@cox.net> wrote:
> Patches welcome. We have about 15 or so such instances.
So we do! ;-)
---
cat-file.c | 2 +-
connect.c | 6 +++---
daemon.c | 2 +-
fetch-clone.c | 4 ++--
git.c | 2 +-
imap-send.c | 2 +-
merge-index.c | 2 +-
| 2 +-
rsh.c | 2 +-
upload-pack.c | 2 +-
10 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/cat-file.c b/cat-file.c
index 1a613f3..6310787 100644
--- a/cat-file.c
+++ b/cat-file.c
@@ -136,7 +136,7 @@ int main(int argc, char **argv)
/* custom pretty-print here */
if (!strcmp(type, "tree"))
- return execl_git_cmd("ls-tree", argv[2], NULL);
+ return execl_git_cmd("ls-tree", argv[2], (char*)0);
buf = read_sha1_file(sha1, type, &size);
if (!buf)
diff --git a/connect.c b/connect.c
index 3f2d65c..a86a111 100644
--- a/connect.c
+++ b/connect.c
@@ -544,7 +544,7 @@ static int git_proxy_connect(int fd[2],
close(pipefd[0][1]);
close(pipefd[1][0]);
close(pipefd[1][1]);
- execlp(git_proxy_command, git_proxy_command, host, port, NULL);
+ execlp(git_proxy_command, git_proxy_command, host, port, (char *)0);
die("exec failed");
}
fd[0] = pipefd[0][0];
@@ -643,7 +643,7 @@ int git_connect(int fd[2], char *url, co
ssh_basename = ssh;
else
ssh_basename++;
- execlp(ssh, ssh_basename, host, command, NULL);
+ execlp(ssh, ssh_basename, host, command, (char *)0);
}
else {
unsetenv(ALTERNATE_DB_ENVIRONMENT);
@@ -651,7 +651,7 @@ int git_connect(int fd[2], char *url, co
unsetenv(GIT_DIR_ENVIRONMENT);
unsetenv(GRAFT_ENVIRONMENT);
unsetenv(INDEX_ENVIRONMENT);
- execlp("sh", "sh", "-c", command, NULL);
+ execlp("sh", "sh", "-c", command, (char *)0);
}
die("exec failed");
}
diff --git a/daemon.c b/daemon.c
index a1ccda3..13d3974 100644
--- a/daemon.c
+++ b/daemon.c
@@ -260,7 +260,7 @@ static int upload(char *dir)
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
/* git-upload-pack only ever reads stuff, so this is safe */
- execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL);
+ execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", (char *)0);
return -1;
}
diff --git a/fetch-clone.c b/fetch-clone.c
index da1b3ff..14a1cdf 100644
--- a/fetch-clone.c
+++ b/fetch-clone.c
@@ -29,7 +29,7 @@ static int finish_pack(const char *pack_
dup2(pipe_fd[1], 1);
close(pipe_fd[0]);
close(pipe_fd[1]);
- execl_git_cmd("index-pack", "-o", idx, pack_tmp_name, NULL);
+ execl_git_cmd("index-pack", "-o", idx, pack_tmp_name, (char *)0);
error("cannot exec git-index-pack <%s> <%s>",
idx, pack_tmp_name);
exit(1);
@@ -106,7 +106,7 @@ int receive_unpack_pack(int fd[2], const
dup2(fd[0], 0);
close(fd[0]);
close(fd[1]);
- execl_git_cmd("unpack-objects", quiet ? "-q" : NULL, NULL);
+ execl_git_cmd("unpack-objects", quiet ? "-q" : (char *)0, (char *)0);
die("git-unpack-objects exec failed");
}
close(fd[0]);
diff --git a/git.c b/git.c
index 0b40e30..8dd7933 100644
--- a/git.c
+++ b/git.c
@@ -253,7 +253,7 @@ static void show_man_page(const char *gi
page = p;
}
- execlp("man", "man", page, NULL);
+ execlp("man", "man", page, (char *)0);
}
static int cmd_version(int argc, const char **argv, char **envp)
diff --git a/imap-send.c b/imap-send.c
index 1b38b3a..825a5cf 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -946,7 +946,7 @@ imap_open_store( imap_server_conf_t *srv
_exit( 127 );
close( a[0] );
close( a[1] );
- execl( "/bin/sh", "sh", "-c", srvc->tunnel, NULL );
+ execl( "/bin/sh", "sh", "-c", srvc->tunnel, (char *)0);
_exit( 127 );
}
diff --git a/merge-index.c b/merge-index.c
index 024196e..24d4b62 100644
--- a/merge-index.c
+++ b/merge-index.c
@@ -23,7 +23,7 @@ static void run_program(void)
arguments[5],
arguments[6],
arguments[7],
- NULL);
+ (char *)0);
die("unable to execute '%s'", pgm);
}
if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status) || WEXITSTATUS(status)) {
--git a/pager.c b/pager.c
index 1364e15..9da76ac 100644
--- a/pager.c
+++ b/pager.c
@@ -11,7 +11,7 @@ static void run_pager(void)
if (!prog)
prog = "less";
setenv("LESS", "-S", 0);
- execlp(prog, prog, NULL);
+ execlp(prog, prog, (char *)0);
}
void setup_pager(void)
diff --git a/rsh.c b/rsh.c
index d665269..92ace2f 100644
--- a/rsh.c
+++ b/rsh.c
@@ -103,7 +103,7 @@ int setup_connection(int *fd_in, int *fd
close(sv[1]);
dup2(sv[0], 0);
dup2(sv[0], 1);
- execlp(ssh, ssh_basename, host, command, NULL);
+ execlp(ssh, ssh_basename, host, command, (char *)0);
}
close(sv[0]);
*fd_in = sv[1];
diff --git a/upload-pack.c b/upload-pack.c
index 47560c9..fbfdbcd 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -89,7 +89,7 @@ static void create_pack_file(void)
dup2(fd[0], 0);
close(fd[0]);
close(fd[1]);
- execl_git_cmd("pack-objects", "--stdout", NULL);
+ execl_git_cmd("pack-objects", "--stdout", (char *)0);
die("git-upload-pack: unable to exec git-pack-objects");
}
-- [mdw]
^ permalink raw reply related
* [PATCH] annotate-tests: override VISUAL when running tests.
From: Mark Wooding @ 2006-03-12 14:00 UTC (permalink / raw)
To: git
From: Mark Wooding <mdw@distorted.org.uk>
The tests hang for me waiting for Emacs with its output directed
somewhere strage, because I hedged my bets and set both EDITOR and
VISUAL to run Emacs.
Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
---
t/annotate-tests.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index 9c5a15a..114938c 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -94,7 +94,7 @@ test_expect_success \
test_expect_success \
'merge-setup part 4' \
'echo "evil merge." >>file &&
- EDITOR=: git commit -a --amend'
+ EDITOR=: VISUAL=: git commit -a --amend'
test_expect_success \
'Two lines blamed on A, one on B, two on B1, one on B2, one on A U Thor' \
^ permalink raw reply related
* Possible --remove-empty bug
From: Marco Costalba @ 2006-03-12 14:12 UTC (permalink / raw)
To: junkio; +Cc: git
>From today git:
$ git-rev-parse HEAD
be767c91724275c4534965c0d25c452b76057602
$ git-rev-list be767c91724275c4534965c0d25c452b76057602 -- imap-send.c
f2561fda364ad984ef1441a80c90b0ee04f1a7c4
$ git-rev-list --remove-empty be767c91724275c4534965c0d25c452b76057602
-- imap-send.c
$
>From git-rev-list documentation:
--remove-empty::
Stop when a given path disappears from the tree.
But isn't it to be intended *after* a path disapperas from the tree?
In this case I would expect to see revision
f2561fda364ad984ef1441a80c90b0ee04f1a7c4 also with --remove-empty
option.
BTW rev f2561fda364ad984ef1441a80c90b0ee04f1a7c4 is the 'Add
git-imap-send, derived from isync 1.0.1.' patch.
Thanks
Marco
^ permalink raw reply
* [BUG] imap-send.c fails to build on OSX
From: Randal L. Schwartz @ 2006-03-12 14:44 UTC (permalink / raw)
To: git
gcc -o imap-send.o -c -g -O2 -Wall -I/sw/include -I/opt/local/include -DSHA1_HEADER='<openssl/sha.h>' imap-send.c
imap-send.c:376: error: static declaration of 'vasprintf' follows non-static declaration
/usr/include/stdio.h:297: error: previous declaration of 'vasprintf' was here
make: *** [imap-send.o] Error 1
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox