git

Форк
0
/
http-push.c 
1987 строк · 50.3 Кб
1
#define USE_THE_REPOSITORY_VARIABLE
2

3
#include "git-compat-util.h"
4
#include "environment.h"
5
#include "hex.h"
6
#include "repository.h"
7
#include "commit.h"
8
#include "tag.h"
9
#include "blob.h"
10
#include "http.h"
11
#include "diff.h"
12
#include "revision.h"
13
#include "remote.h"
14
#include "list-objects.h"
15
#include "setup.h"
16
#include "sigchain.h"
17
#include "strvec.h"
18
#include "tree.h"
19
#include "tree-walk.h"
20
#include "url.h"
21
#include "packfile.h"
22
#include "object-store-ll.h"
23
#include "commit-reach.h"
24

25
#ifdef EXPAT_NEEDS_XMLPARSE_H
26
#include <xmlparse.h>
27
#else
28
#include <expat.h>
29
#endif
30

31
static const char http_push_usage[] =
32
"git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
33

34
#ifndef XML_STATUS_OK
35
enum XML_Status {
36
  XML_STATUS_OK = 1,
37
  XML_STATUS_ERROR = 0
38
};
39
#define XML_STATUS_OK    1
40
#define XML_STATUS_ERROR 0
41
#endif
42

43
#define PREV_BUF_SIZE 4096
44

45
/* DAV methods */
46
#define DAV_LOCK "LOCK"
47
#define DAV_MKCOL "MKCOL"
48
#define DAV_MOVE "MOVE"
49
#define DAV_PROPFIND "PROPFIND"
50
#define DAV_PUT "PUT"
51
#define DAV_UNLOCK "UNLOCK"
52
#define DAV_DELETE "DELETE"
53

54
/* DAV lock flags */
55
#define DAV_PROP_LOCKWR (1u << 0)
56
#define DAV_PROP_LOCKEX (1u << 1)
57
#define DAV_LOCK_OK (1u << 2)
58

59
/* DAV XML properties */
60
#define DAV_CTX_LOCKENTRY ".multistatus.response.propstat.prop.supportedlock.lockentry"
61
#define DAV_CTX_LOCKTYPE_WRITE ".multistatus.response.propstat.prop.supportedlock.lockentry.locktype.write"
62
#define DAV_CTX_LOCKTYPE_EXCLUSIVE ".multistatus.response.propstat.prop.supportedlock.lockentry.lockscope.exclusive"
63
#define DAV_ACTIVELOCK_OWNER ".prop.lockdiscovery.activelock.owner.href"
64
#define DAV_ACTIVELOCK_TIMEOUT ".prop.lockdiscovery.activelock.timeout"
65
#define DAV_ACTIVELOCK_TOKEN ".prop.lockdiscovery.activelock.locktoken.href"
66
#define DAV_PROPFIND_RESP ".multistatus.response"
67
#define DAV_PROPFIND_NAME ".multistatus.response.href"
68
#define DAV_PROPFIND_COLLECTION ".multistatus.response.propstat.prop.resourcetype.collection"
69

70
/* DAV request body templates */
71
#define PROPFIND_SUPPORTEDLOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop xmlns:R=\"%s\">\n<D:supportedlock/>\n</D:prop>\n</D:propfind>"
72
#define PROPFIND_ALL_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop/>\n</D:propfind>"
73
#define LOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:lockinfo xmlns:D=\"DAV:\">\n<D:lockscope><D:exclusive/></D:lockscope>\n<D:locktype><D:write/></D:locktype>\n<D:owner>\n<D:href>mailto:%s</D:href>\n</D:owner>\n</D:lockinfo>"
74

75
#define LOCK_TIME 600
76
#define LOCK_REFRESH 30
77

78
/* Remember to update object flag allocation in object.h */
79
#define LOCAL    (1u<<11)
80
#define REMOTE   (1u<<12)
81
#define FETCHING (1u<<13)
82
#define PUSHING  (1u<<14)
83

84
/* We allow "recursive" symbolic refs. Only within reason, though */
85
#define MAXDEPTH 5
86

87
static int pushing;
88
static int aborted;
89
static signed char remote_dir_exists[256];
90

91
static int push_verbosely;
92
static int push_all = MATCH_REFS_NONE;
93
static int force_all;
94
static int dry_run;
95
static int helper_status;
96

97
static struct object_list *objects;
98

99
struct repo {
100
	char *url;
101
	char *path;
102
	int path_len;
103
	int has_info_refs;
104
	int can_update_info_refs;
105
	int has_info_packs;
106
	struct packed_git *packs;
107
	struct remote_lock *locks;
108
};
109

110
static struct repo *repo;
111

112
enum transfer_state {
113
	NEED_FETCH,
114
	RUN_FETCH_LOOSE,
115
	RUN_FETCH_PACKED,
116
	NEED_PUSH,
117
	RUN_MKCOL,
118
	RUN_PUT,
119
	RUN_MOVE,
120
	ABORTED,
121
	COMPLETE
122
};
123

124
struct transfer_request {
125
	struct object *obj;
126
	struct packed_git *target;
127
	char *url;
128
	char *dest;
129
	struct remote_lock *lock;
130
	struct curl_slist *headers;
131
	struct buffer buffer;
132
	enum transfer_state state;
133
	CURLcode curl_result;
134
	char errorstr[CURL_ERROR_SIZE];
135
	long http_code;
136
	void *userData;
137
	struct active_request_slot *slot;
138
	struct transfer_request *next;
139
};
140

141
static struct transfer_request *request_queue_head;
142

143
struct xml_ctx {
144
	char *name;
145
	int len;
146
	char *cdata;
147
	void (*userFunc)(struct xml_ctx *ctx, int tag_closed);
148
	void *userData;
149
};
150

151
struct remote_lock {
152
	char *url;
153
	char *owner;
154
	char *token;
155
	char tmpfile_suffix[GIT_MAX_HEXSZ + 1];
156
	time_t start_time;
157
	long timeout;
158
	int refreshing;
159
	struct remote_lock *next;
160
};
161

162
/* Flags that control remote_ls processing */
163
#define PROCESS_FILES (1u << 0)
164
#define PROCESS_DIRS  (1u << 1)
165
#define RECURSIVE     (1u << 2)
166

167
/* Flags that remote_ls passes to callback functions */
168
#define IS_DIR (1u << 0)
169

170
struct remote_ls_ctx {
171
	char *path;
172
	void (*userFunc)(struct remote_ls_ctx *ls);
173
	void *userData;
174
	int flags;
175
	char *dentry_name;
176
	int dentry_flags;
177
	struct remote_ls_ctx *parent;
178
};
179

180
/* get_dav_token_headers options */
181
enum dav_header_flag {
182
	DAV_HEADER_IF = (1u << 0),
183
	DAV_HEADER_LOCK = (1u << 1),
184
	DAV_HEADER_TIMEOUT = (1u << 2)
185
};
186

187
static char *xml_entities(const char *s)
188
{
189
	struct strbuf buf = STRBUF_INIT;
190
	strbuf_addstr_xml_quoted(&buf, s);
191
	return strbuf_detach(&buf, NULL);
192
}
193

194
static void curl_setup_http_get(CURL *curl, const char *url,
195
		const char *custom_req)
196
{
197
	curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
198
	curl_easy_setopt(curl, CURLOPT_URL, url);
199
	curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req);
200
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_null);
201
}
202

203
static void curl_setup_http(CURL *curl, const char *url,
204
		const char *custom_req, struct buffer *buffer,
205
		curl_write_callback write_fn)
206
{
207
	curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
208
	curl_easy_setopt(curl, CURLOPT_URL, url);
209
	curl_easy_setopt(curl, CURLOPT_INFILE, buffer);
210
	curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len);
211
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
212
	curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer);
213
	curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer);
214
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
215
	curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
216
	curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req);
217
	curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
218
}
219

220
static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
221
{
222
	struct strbuf buf = STRBUF_INIT;
223
	struct curl_slist *dav_headers = http_copy_default_headers();
224

225
	if (options & DAV_HEADER_IF) {
226
		strbuf_addf(&buf, "If: (<%s>)", lock->token);
227
		dav_headers = curl_slist_append(dav_headers, buf.buf);
228
		strbuf_reset(&buf);
229
	}
230
	if (options & DAV_HEADER_LOCK) {
231
		strbuf_addf(&buf, "Lock-Token: <%s>", lock->token);
232
		dav_headers = curl_slist_append(dav_headers, buf.buf);
233
		strbuf_reset(&buf);
234
	}
235
	if (options & DAV_HEADER_TIMEOUT) {
236
		strbuf_addf(&buf, "Timeout: Second-%ld", lock->timeout);
237
		dav_headers = curl_slist_append(dav_headers, buf.buf);
238
		strbuf_reset(&buf);
239
	}
240
	strbuf_release(&buf);
241

242
	return dav_headers;
243
}
244

245
static void finish_request(struct transfer_request *request);
246
static void release_request(struct transfer_request *request);
247

248
static void process_response(void *callback_data)
249
{
250
	struct transfer_request *request =
251
		(struct transfer_request *)callback_data;
252

253
	finish_request(request);
254
}
255

256
static void start_fetch_loose(struct transfer_request *request)
257
{
258
	struct active_request_slot *slot;
259
	struct http_object_request *obj_req;
260

261
	obj_req = new_http_object_request(repo->url, &request->obj->oid);
262
	if (!obj_req) {
263
		request->state = ABORTED;
264
		return;
265
	}
266

267
	slot = obj_req->slot;
268
	slot->callback_func = process_response;
269
	slot->callback_data = request;
270
	request->slot = slot;
271
	request->userData = obj_req;
272

273
	/* Try to get the request started, abort the request on error */
274
	request->state = RUN_FETCH_LOOSE;
275
	if (!start_active_slot(slot)) {
276
		fprintf(stderr, "Unable to start GET request\n");
277
		repo->can_update_info_refs = 0;
278
		release_http_object_request(obj_req);
279
		release_request(request);
280
	}
281
}
282

283
static void start_mkcol(struct transfer_request *request)
284
{
285
	char *hex = oid_to_hex(&request->obj->oid);
286
	struct active_request_slot *slot;
287

288
	request->url = get_remote_object_url(repo->url, hex, 1);
289

290
	slot = get_active_slot();
291
	slot->callback_func = process_response;
292
	slot->callback_data = request;
293
	curl_setup_http_get(slot->curl, request->url, DAV_MKCOL);
294
	curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
295

296
	if (start_active_slot(slot)) {
297
		request->slot = slot;
298
		request->state = RUN_MKCOL;
299
	} else {
300
		request->state = ABORTED;
301
		FREE_AND_NULL(request->url);
302
	}
303
}
304

305
static void start_fetch_packed(struct transfer_request *request)
306
{
307
	struct packed_git *target;
308

309
	struct transfer_request *check_request = request_queue_head;
310
	struct http_pack_request *preq;
311

312
	target = find_sha1_pack(request->obj->oid.hash, repo->packs);
313
	if (!target) {
314
		fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", oid_to_hex(&request->obj->oid));
315
		repo->can_update_info_refs = 0;
316
		release_request(request);
317
		return;
318
	}
319
	close_pack_index(target);
320
	request->target = target;
321

322
	fprintf(stderr,	"Fetching pack %s\n",
323
		hash_to_hex(target->hash));
324
	fprintf(stderr, " which contains %s\n", oid_to_hex(&request->obj->oid));
325

326
	preq = new_http_pack_request(target->hash, repo->url);
327
	if (!preq) {
328
		repo->can_update_info_refs = 0;
329
		return;
330
	}
331

332
	/* Make sure there isn't another open request for this pack */
333
	while (check_request) {
334
		if (check_request->state == RUN_FETCH_PACKED &&
335
		    !strcmp(check_request->url, preq->url)) {
336
			release_http_pack_request(preq);
337
			release_request(request);
338
			return;
339
		}
340
		check_request = check_request->next;
341
	}
342

343
	preq->slot->callback_func = process_response;
344
	preq->slot->callback_data = request;
345
	request->slot = preq->slot;
346
	request->userData = preq;
347

348
	/* Try to get the request started, abort the request on error */
349
	request->state = RUN_FETCH_PACKED;
350
	if (!start_active_slot(preq->slot)) {
351
		fprintf(stderr, "Unable to start GET request\n");
352
		release_http_pack_request(preq);
353
		repo->can_update_info_refs = 0;
354
		release_request(request);
355
	}
356
}
357

358
static void start_put(struct transfer_request *request)
359
{
360
	char *hex = oid_to_hex(&request->obj->oid);
361
	struct active_request_slot *slot;
362
	struct strbuf buf = STRBUF_INIT;
363
	enum object_type type;
364
	char hdr[50];
365
	void *unpacked;
366
	unsigned long len;
367
	int hdrlen;
368
	ssize_t size;
369
	git_zstream stream;
370

371
	unpacked = repo_read_object_file(the_repository, &request->obj->oid,
372
					 &type, &len);
373
	hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
374

375
	/* Set it up */
376
	git_deflate_init(&stream, zlib_compression_level);
377
	size = git_deflate_bound(&stream, len + hdrlen);
378
	strbuf_init(&request->buffer.buf, size);
379
	request->buffer.posn = 0;
380

381
	/* Compress it */
382
	stream.next_out = (unsigned char *)request->buffer.buf.buf;
383
	stream.avail_out = size;
384

385
	/* First header.. */
386
	stream.next_in = (void *)hdr;
387
	stream.avail_in = hdrlen;
388
	while (git_deflate(&stream, 0) == Z_OK)
389
		; /* nothing */
390

391
	/* Then the data itself.. */
392
	stream.next_in = unpacked;
393
	stream.avail_in = len;
394
	while (git_deflate(&stream, Z_FINISH) == Z_OK)
395
		; /* nothing */
396
	git_deflate_end(&stream);
397
	free(unpacked);
398

399
	request->buffer.buf.len = stream.total_out;
400

401
	strbuf_addstr(&buf, "Destination: ");
402
	append_remote_object_url(&buf, repo->url, hex, 0);
403
	request->dest = strbuf_detach(&buf, NULL);
404

405
	append_remote_object_url(&buf, repo->url, hex, 0);
406
	strbuf_add(&buf, request->lock->tmpfile_suffix, the_hash_algo->hexsz + 1);
407
	request->url = strbuf_detach(&buf, NULL);
408

409
	slot = get_active_slot();
410
	slot->callback_func = process_response;
411
	slot->callback_data = request;
412
	curl_setup_http(slot->curl, request->url, DAV_PUT,
413
			&request->buffer, fwrite_null);
414

415
	if (start_active_slot(slot)) {
416
		request->slot = slot;
417
		request->state = RUN_PUT;
418
	} else {
419
		request->state = ABORTED;
420
		FREE_AND_NULL(request->url);
421
	}
422
}
423

424
static void start_move(struct transfer_request *request)
425
{
426
	struct active_request_slot *slot;
427
	struct curl_slist *dav_headers = http_copy_default_headers();
428

429
	slot = get_active_slot();
430
	slot->callback_func = process_response;
431
	slot->callback_data = request;
432
	curl_setup_http_get(slot->curl, request->url, DAV_MOVE);
433
	dav_headers = curl_slist_append(dav_headers, request->dest);
434
	dav_headers = curl_slist_append(dav_headers, "Overwrite: T");
435
	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
436

437
	if (start_active_slot(slot)) {
438
		request->slot = slot;
439
		request->state = RUN_MOVE;
440
	} else {
441
		request->state = ABORTED;
442
		FREE_AND_NULL(request->url);
443
	}
444
}
445

446
static int refresh_lock(struct remote_lock *lock)
447
{
448
	struct active_request_slot *slot;
449
	struct slot_results results;
450
	struct curl_slist *dav_headers;
451
	int rc = 0;
452

453
	lock->refreshing = 1;
454

455
	dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF | DAV_HEADER_TIMEOUT);
456

457
	slot = get_active_slot();
458
	slot->results = &results;
459
	curl_setup_http_get(slot->curl, lock->url, DAV_LOCK);
460
	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
461

462
	if (start_active_slot(slot)) {
463
		run_active_slot(slot);
464
		if (results.curl_result != CURLE_OK) {
465
			fprintf(stderr, "LOCK HTTP error %ld\n",
466
				results.http_code);
467
		} else {
468
			lock->start_time = time(NULL);
469
			rc = 1;
470
		}
471
	}
472

473
	lock->refreshing = 0;
474
	curl_slist_free_all(dav_headers);
475

476
	return rc;
477
}
478

479
static void check_locks(void)
480
{
481
	struct remote_lock *lock = repo->locks;
482
	time_t current_time = time(NULL);
483
	int time_remaining;
484

485
	while (lock) {
486
		time_remaining = lock->start_time + lock->timeout -
487
			current_time;
488
		if (!lock->refreshing && time_remaining < LOCK_REFRESH) {
489
			if (!refresh_lock(lock)) {
490
				fprintf(stderr,
491
					"Unable to refresh lock for %s\n",
492
					lock->url);
493
				aborted = 1;
494
				return;
495
			}
496
		}
497
		lock = lock->next;
498
	}
499
}
500

501
static void release_request(struct transfer_request *request)
502
{
503
	struct transfer_request *entry = request_queue_head;
504

505
	if (request == request_queue_head) {
506
		request_queue_head = request->next;
507
	} else {
508
		while (entry && entry->next != request)
509
			entry = entry->next;
510
		if (entry)
511
			entry->next = request->next;
512
	}
513

514
	free(request->url);
515
	free(request);
516
}
517

518
static void finish_request(struct transfer_request *request)
519
{
520
	struct http_pack_request *preq;
521
	struct http_object_request *obj_req;
522

523
	request->curl_result = request->slot->curl_result;
524
	request->http_code = request->slot->http_code;
525
	request->slot = NULL;
526

527
	/* Keep locks active */
528
	check_locks();
529

530
	if (request->headers)
531
		curl_slist_free_all(request->headers);
532

533
	/* URL is reused for MOVE after PUT and used during FETCH */
534
	if (request->state != RUN_PUT && request->state != RUN_FETCH_PACKED) {
535
		FREE_AND_NULL(request->url);
536
	}
537

538
	if (request->state == RUN_MKCOL) {
539
		if (request->curl_result == CURLE_OK ||
540
		    request->http_code == 405) {
541
			remote_dir_exists[request->obj->oid.hash[0]] = 1;
542
			start_put(request);
543
		} else {
544
			fprintf(stderr, "MKCOL %s failed, aborting (%d/%ld)\n",
545
				oid_to_hex(&request->obj->oid),
546
				request->curl_result, request->http_code);
547
			request->state = ABORTED;
548
			aborted = 1;
549
		}
550
	} else if (request->state == RUN_PUT) {
551
		if (request->curl_result == CURLE_OK) {
552
			start_move(request);
553
		} else {
554
			fprintf(stderr,	"PUT %s failed, aborting (%d/%ld)\n",
555
				oid_to_hex(&request->obj->oid),
556
				request->curl_result, request->http_code);
557
			request->state = ABORTED;
558
			aborted = 1;
559
		}
560
	} else if (request->state == RUN_MOVE) {
561
		if (request->curl_result == CURLE_OK) {
562
			if (push_verbosely)
563
				fprintf(stderr, "    sent %s\n",
564
					oid_to_hex(&request->obj->oid));
565
			request->obj->flags |= REMOTE;
566
			release_request(request);
567
		} else {
568
			fprintf(stderr, "MOVE %s failed, aborting (%d/%ld)\n",
569
				oid_to_hex(&request->obj->oid),
570
				request->curl_result, request->http_code);
571
			request->state = ABORTED;
572
			aborted = 1;
573
		}
574
	} else if (request->state == RUN_FETCH_LOOSE) {
575
		obj_req = (struct http_object_request *)request->userData;
576

577
		if (finish_http_object_request(obj_req) == 0)
578
			if (obj_req->rename == 0)
579
				request->obj->flags |= (LOCAL | REMOTE);
580

581
		/* Try fetching packed if necessary */
582
		if (request->obj->flags & LOCAL) {
583
			release_http_object_request(obj_req);
584
			release_request(request);
585
		} else
586
			start_fetch_packed(request);
587

588
	} else if (request->state == RUN_FETCH_PACKED) {
589
		int fail = 1;
590
		if (request->curl_result != CURLE_OK) {
591
			fprintf(stderr, "Unable to get pack file %s\n%s",
592
				request->url, curl_errorstr);
593
		} else {
594
			preq = (struct http_pack_request *)request->userData;
595

596
			if (preq) {
597
				if (finish_http_pack_request(preq) == 0)
598
					fail = 0;
599
				release_http_pack_request(preq);
600
			}
601
		}
602
		if (fail)
603
			repo->can_update_info_refs = 0;
604
		else
605
			http_install_packfile(request->target, &repo->packs);
606
		release_request(request);
607
	}
608
}
609

610
static int is_running_queue;
611
static int fill_active_slot(void *data UNUSED)
612
{
613
	struct transfer_request *request;
614

615
	if (aborted || !is_running_queue)
616
		return 0;
617

618
	for (request = request_queue_head; request; request = request->next) {
619
		if (request->state == NEED_FETCH) {
620
			start_fetch_loose(request);
621
			return 1;
622
		} else if (pushing && request->state == NEED_PUSH) {
623
			if (remote_dir_exists[request->obj->oid.hash[0]] == 1) {
624
				start_put(request);
625
			} else {
626
				start_mkcol(request);
627
			}
628
			return 1;
629
		}
630
	}
631
	return 0;
632
}
633

634
static void get_remote_object_list(unsigned char parent);
635

636
static void add_fetch_request(struct object *obj)
637
{
638
	struct transfer_request *request;
639

640
	check_locks();
641

642
	/*
643
	 * Don't fetch the object if it's known to exist locally
644
	 * or is already in the request queue
645
	 */
646
	if (remote_dir_exists[obj->oid.hash[0]] == -1)
647
		get_remote_object_list(obj->oid.hash[0]);
648
	if (obj->flags & (LOCAL | FETCHING))
649
		return;
650

651
	obj->flags |= FETCHING;
652
	request = xmalloc(sizeof(*request));
653
	request->obj = obj;
654
	request->url = NULL;
655
	request->lock = NULL;
656
	request->headers = NULL;
657
	request->state = NEED_FETCH;
658
	request->next = request_queue_head;
659
	request_queue_head = request;
660

661
	fill_active_slots();
662
	step_active_slots();
663
}
664

665
static int add_send_request(struct object *obj, struct remote_lock *lock)
666
{
667
	struct transfer_request *request;
668
	struct packed_git *target;
669

670
	/* Keep locks active */
671
	check_locks();
672

673
	/*
674
	 * Don't push the object if it's known to exist on the remote
675
	 * or is already in the request queue
676
	 */
677
	if (remote_dir_exists[obj->oid.hash[0]] == -1)
678
		get_remote_object_list(obj->oid.hash[0]);
679
	if (obj->flags & (REMOTE | PUSHING))
680
		return 0;
681
	target = find_sha1_pack(obj->oid.hash, repo->packs);
682
	if (target) {
683
		obj->flags |= REMOTE;
684
		return 0;
685
	}
686

687
	obj->flags |= PUSHING;
688
	request = xmalloc(sizeof(*request));
689
	request->obj = obj;
690
	request->url = NULL;
691
	request->lock = lock;
692
	request->headers = NULL;
693
	request->state = NEED_PUSH;
694
	request->next = request_queue_head;
695
	request_queue_head = request;
696

697
	fill_active_slots();
698
	step_active_slots();
699

700
	return 1;
701
}
702

703
static int fetch_indices(void)
704
{
705
	int ret;
706

707
	if (push_verbosely)
708
		fprintf(stderr, "Getting pack list\n");
709

710
	switch (http_get_info_packs(repo->url, &repo->packs)) {
711
	case HTTP_OK:
712
	case HTTP_MISSING_TARGET:
713
		ret = 0;
714
		break;
715
	default:
716
		ret = -1;
717
	}
718

719
	return ret;
720
}
721

722
static void one_remote_object(const struct object_id *oid)
723
{
724
	struct object *obj;
725

726
	obj = lookup_object(the_repository, oid);
727
	if (!obj)
728
		obj = parse_object(the_repository, oid);
729

730
	/* Ignore remote objects that don't exist locally */
731
	if (!obj)
732
		return;
733

734
	obj->flags |= REMOTE;
735
	if (!object_list_contains(objects, obj))
736
		object_list_insert(obj, &objects);
737
}
738

739
static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed)
740
{
741
	int *lock_flags = (int *)ctx->userData;
742

743
	if (tag_closed) {
744
		if (!strcmp(ctx->name, DAV_CTX_LOCKENTRY)) {
745
			if ((*lock_flags & DAV_PROP_LOCKEX) &&
746
			    (*lock_flags & DAV_PROP_LOCKWR)) {
747
				*lock_flags |= DAV_LOCK_OK;
748
			}
749
			*lock_flags &= DAV_LOCK_OK;
750
		} else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_WRITE)) {
751
			*lock_flags |= DAV_PROP_LOCKWR;
752
		} else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_EXCLUSIVE)) {
753
			*lock_flags |= DAV_PROP_LOCKEX;
754
		}
755
	}
756
}
757

758
static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
759
{
760
	struct remote_lock *lock = (struct remote_lock *)ctx->userData;
761
	git_hash_ctx hash_ctx;
762
	unsigned char lock_token_hash[GIT_MAX_RAWSZ];
763

764
	if (tag_closed && ctx->cdata) {
765
		if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) {
766
			lock->owner = xstrdup(ctx->cdata);
767
		} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) {
768
			const char *arg;
769
			if (skip_prefix(ctx->cdata, "Second-", &arg))
770
				lock->timeout = strtol(arg, NULL, 10);
771
		} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
772
			lock->token = xstrdup(ctx->cdata);
773

774
			the_hash_algo->init_fn(&hash_ctx);
775
			the_hash_algo->update_fn(&hash_ctx, lock->token, strlen(lock->token));
776
			the_hash_algo->final_fn(lock_token_hash, &hash_ctx);
777

778
			lock->tmpfile_suffix[0] = '_';
779
			memcpy(lock->tmpfile_suffix + 1, hash_to_hex(lock_token_hash), the_hash_algo->hexsz);
780
		}
781
	}
782
}
783

784
static void one_remote_ref(const char *refname);
785

786
static void
787
xml_start_tag(void *userData, const char *name, const char **atts UNUSED)
788
{
789
	struct xml_ctx *ctx = (struct xml_ctx *)userData;
790
	const char *c = strchr(name, ':');
791
	int old_namelen, new_len;
792

793
	if (!c)
794
		c = name;
795
	else
796
		c++;
797

798
	old_namelen = strlen(ctx->name);
799
	new_len = old_namelen + strlen(c) + 2;
800

801
	if (new_len > ctx->len) {
802
		ctx->name = xrealloc(ctx->name, new_len);
803
		ctx->len = new_len;
804
	}
805
	xsnprintf(ctx->name + old_namelen, ctx->len - old_namelen, ".%s", c);
806

807
	FREE_AND_NULL(ctx->cdata);
808

809
	ctx->userFunc(ctx, 0);
810
}
811

812
static void
813
xml_end_tag(void *userData, const char *name)
814
{
815
	struct xml_ctx *ctx = (struct xml_ctx *)userData;
816
	const char *c = strchr(name, ':');
817
	char *ep;
818

819
	ctx->userFunc(ctx, 1);
820

821
	if (!c)
822
		c = name;
823
	else
824
		c++;
825

826
	ep = ctx->name + strlen(ctx->name) - strlen(c) - 1;
827
	*ep = 0;
828
}
829

830
static void
831
xml_cdata(void *userData, const XML_Char *s, int len)
832
{
833
	struct xml_ctx *ctx = (struct xml_ctx *)userData;
834
	free(ctx->cdata);
835
	ctx->cdata = xmemdupz(s, len);
836
}
837

838
static struct remote_lock *lock_remote(const char *path, long timeout)
839
{
840
	struct active_request_slot *slot;
841
	struct slot_results results;
842
	struct buffer out_buffer = { STRBUF_INIT, 0 };
843
	struct strbuf in_buffer = STRBUF_INIT;
844
	char *url;
845
	char *ep;
846
	char timeout_header[25];
847
	struct remote_lock *lock = NULL;
848
	struct curl_slist *dav_headers = http_copy_default_headers();
849
	struct xml_ctx ctx;
850
	char *escaped;
851

852
	url = xstrfmt("%s%s", repo->url, path);
853

854
	/* Make sure leading directories exist for the remote ref */
855
	ep = strchr(url + strlen(repo->url) + 1, '/');
856
	while (ep) {
857
		char saved_character = ep[1];
858
		ep[1] = '\0';
859
		slot = get_active_slot();
860
		slot->results = &results;
861
		curl_setup_http_get(slot->curl, url, DAV_MKCOL);
862
		if (start_active_slot(slot)) {
863
			run_active_slot(slot);
864
			if (results.curl_result != CURLE_OK &&
865
			    results.http_code != 405) {
866
				fprintf(stderr,
867
					"Unable to create branch path %s\n",
868
					url);
869
				free(url);
870
				return NULL;
871
			}
872
		} else {
873
			fprintf(stderr, "Unable to start MKCOL request\n");
874
			free(url);
875
			return NULL;
876
		}
877
		ep[1] = saved_character;
878
		ep = strchr(ep + 1, '/');
879
	}
880

881
	escaped = xml_entities(ident_default_email());
882
	strbuf_addf(&out_buffer.buf, LOCK_REQUEST, escaped);
883
	free(escaped);
884

885
	xsnprintf(timeout_header, sizeof(timeout_header), "Timeout: Second-%ld", timeout);
886
	dav_headers = curl_slist_append(dav_headers, timeout_header);
887
	dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
888

889
	slot = get_active_slot();
890
	slot->results = &results;
891
	curl_setup_http(slot->curl, url, DAV_LOCK, &out_buffer, fwrite_buffer);
892
	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
893
	curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer);
894

895
	CALLOC_ARRAY(lock, 1);
896
	lock->timeout = -1;
897

898
	if (start_active_slot(slot)) {
899
		run_active_slot(slot);
900
		if (results.curl_result == CURLE_OK) {
901
			XML_Parser parser = XML_ParserCreate(NULL);
902
			enum XML_Status result;
903
			ctx.name = xcalloc(10, 1);
904
			ctx.len = 0;
905
			ctx.cdata = NULL;
906
			ctx.userFunc = handle_new_lock_ctx;
907
			ctx.userData = lock;
908
			XML_SetUserData(parser, &ctx);
909
			XML_SetElementHandler(parser, xml_start_tag,
910
					      xml_end_tag);
911
			XML_SetCharacterDataHandler(parser, xml_cdata);
912
			result = XML_Parse(parser, in_buffer.buf,
913
					   in_buffer.len, 1);
914
			free(ctx.name);
915
			if (result != XML_STATUS_OK) {
916
				fprintf(stderr, "XML error: %s\n",
917
					XML_ErrorString(
918
						XML_GetErrorCode(parser)));
919
				lock->timeout = -1;
920
			}
921
			XML_ParserFree(parser);
922
		} else {
923
			fprintf(stderr,
924
				"error: curl result=%d, HTTP code=%ld\n",
925
				results.curl_result, results.http_code);
926
		}
927
	} else {
928
		fprintf(stderr, "Unable to start LOCK request\n");
929
	}
930

931
	curl_slist_free_all(dav_headers);
932
	strbuf_release(&out_buffer.buf);
933
	strbuf_release(&in_buffer);
934

935
	if (lock->token == NULL || lock->timeout <= 0) {
936
		free(lock->token);
937
		free(lock->owner);
938
		free(url);
939
		FREE_AND_NULL(lock);
940
	} else {
941
		lock->url = url;
942
		lock->start_time = time(NULL);
943
		lock->next = repo->locks;
944
		repo->locks = lock;
945
	}
946

947
	return lock;
948
}
949

950
static int unlock_remote(struct remote_lock *lock)
951
{
952
	struct active_request_slot *slot;
953
	struct slot_results results;
954
	struct remote_lock *prev = repo->locks;
955
	struct curl_slist *dav_headers;
956
	int rc = 0;
957

958
	dav_headers = get_dav_token_headers(lock, DAV_HEADER_LOCK);
959

960
	slot = get_active_slot();
961
	slot->results = &results;
962
	curl_setup_http_get(slot->curl, lock->url, DAV_UNLOCK);
963
	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
964

965
	if (start_active_slot(slot)) {
966
		run_active_slot(slot);
967
		if (results.curl_result == CURLE_OK)
968
			rc = 1;
969
		else
970
			fprintf(stderr, "UNLOCK HTTP error %ld\n",
971
				results.http_code);
972
	} else {
973
		fprintf(stderr, "Unable to start UNLOCK request\n");
974
	}
975

976
	curl_slist_free_all(dav_headers);
977

978
	if (repo->locks == lock) {
979
		repo->locks = lock->next;
980
	} else {
981
		while (prev && prev->next != lock)
982
			prev = prev->next;
983
		if (prev)
984
			prev->next = lock->next;
985
	}
986

987
	free(lock->owner);
988
	free(lock->url);
989
	free(lock->token);
990
	free(lock);
991

992
	return rc;
993
}
994

995
static void remove_locks(void)
996
{
997
	struct remote_lock *lock = repo->locks;
998

999
	fprintf(stderr, "Removing remote locks...\n");
1000
	while (lock) {
1001
		struct remote_lock *next = lock->next;
1002
		unlock_remote(lock);
1003
		lock = next;
1004
	}
1005
}
1006

1007
static void remove_locks_on_signal(int signo)
1008
{
1009
	remove_locks();
1010
	sigchain_pop(signo);
1011
	raise(signo);
1012
}
1013

1014
static void remote_ls(const char *path, int flags,
1015
		      void (*userFunc)(struct remote_ls_ctx *ls),
1016
		      void *userData);
1017

1018
/* extract hex from sharded "xx/x{38}" filename */
1019
static int get_oid_hex_from_objpath(const char *path, struct object_id *oid)
1020
{
1021
	memset(oid->hash, 0, GIT_MAX_RAWSZ);
1022
	oid->algo = hash_algo_by_ptr(the_hash_algo);
1023

1024
	if (strlen(path) != the_hash_algo->hexsz + 1)
1025
		return -1;
1026

1027
	if (hex_to_bytes(oid->hash, path, 1))
1028
		return -1;
1029
	path += 2;
1030
	path++; /* skip '/' */
1031

1032
	return hex_to_bytes(oid->hash + 1, path, the_hash_algo->rawsz - 1);
1033
}
1034

1035
static void process_ls_object(struct remote_ls_ctx *ls)
1036
{
1037
	unsigned int *parent = (unsigned int *)ls->userData;
1038
	const char *path = ls->dentry_name;
1039
	struct object_id oid;
1040

1041
	if (!strcmp(ls->path, ls->dentry_name) && (ls->flags & IS_DIR)) {
1042
		remote_dir_exists[*parent] = 1;
1043
		return;
1044
	}
1045

1046
	if (!skip_prefix(path, "objects/", &path) ||
1047
	    get_oid_hex_from_objpath(path, &oid))
1048
		return;
1049

1050
	one_remote_object(&oid);
1051
}
1052

1053
static void process_ls_ref(struct remote_ls_ctx *ls)
1054
{
1055
	if (!strcmp(ls->path, ls->dentry_name) && (ls->dentry_flags & IS_DIR)) {
1056
		fprintf(stderr, "  %s\n", ls->dentry_name);
1057
		return;
1058
	}
1059

1060
	if (!(ls->dentry_flags & IS_DIR))
1061
		one_remote_ref(ls->dentry_name);
1062
}
1063

1064
static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
1065
{
1066
	struct remote_ls_ctx *ls = (struct remote_ls_ctx *)ctx->userData;
1067

1068
	if (tag_closed) {
1069
		if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && ls->dentry_name) {
1070
			if (ls->dentry_flags & IS_DIR) {
1071

1072
				/* ensure collection names end with slash */
1073
				str_end_url_with_slash(ls->dentry_name, &ls->dentry_name);
1074

1075
				if (ls->flags & PROCESS_DIRS) {
1076
					ls->userFunc(ls);
1077
				}
1078
				if (strcmp(ls->dentry_name, ls->path) &&
1079
				    ls->flags & RECURSIVE) {
1080
					remote_ls(ls->dentry_name,
1081
						  ls->flags,
1082
						  ls->userFunc,
1083
						  ls->userData);
1084
				}
1085
			} else if (ls->flags & PROCESS_FILES) {
1086
				ls->userFunc(ls);
1087
			}
1088
		} else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
1089
			char *path = ctx->cdata;
1090
			if (*ctx->cdata == 'h') {
1091
				path = strstr(path, "//");
1092
				if (path) {
1093
					path = strchr(path+2, '/');
1094
				}
1095
			}
1096
			if (path) {
1097
				const char *url = repo->url;
1098
				if (repo->path)
1099
					url = repo->path;
1100
				if (strncmp(path, url, repo->path_len))
1101
					error("Parsed path '%s' does not match url: '%s'",
1102
					      path, url);
1103
				else {
1104
					path += repo->path_len;
1105
					ls->dentry_name = xstrdup(path);
1106
				}
1107
			}
1108
		} else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
1109
			ls->dentry_flags |= IS_DIR;
1110
		}
1111
	} else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
1112
		FREE_AND_NULL(ls->dentry_name);
1113
		ls->dentry_flags = 0;
1114
	}
1115
}
1116

1117
/*
1118
 * NEEDSWORK: remote_ls() ignores info/refs on the remote side.  But it
1119
 * should _only_ heed the information from that file, instead of trying to
1120
 * determine the refs from the remote file system (badly: it does not even
1121
 * know about packed-refs).
1122
 */
1123
static void remote_ls(const char *path, int flags,
1124
		      void (*userFunc)(struct remote_ls_ctx *ls),
1125
		      void *userData)
1126
{
1127
	char *url = xstrfmt("%s%s", repo->url, path);
1128
	struct active_request_slot *slot;
1129
	struct slot_results results;
1130
	struct strbuf in_buffer = STRBUF_INIT;
1131
	struct buffer out_buffer = { STRBUF_INIT, 0 };
1132
	struct curl_slist *dav_headers = http_copy_default_headers();
1133
	struct xml_ctx ctx;
1134
	struct remote_ls_ctx ls;
1135

1136
	ls.flags = flags;
1137
	ls.path = xstrdup(path);
1138
	ls.dentry_name = NULL;
1139
	ls.dentry_flags = 0;
1140
	ls.userData = userData;
1141
	ls.userFunc = userFunc;
1142

1143
	strbuf_addstr(&out_buffer.buf, PROPFIND_ALL_REQUEST);
1144

1145
	dav_headers = curl_slist_append(dav_headers, "Depth: 1");
1146
	dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1147

1148
	slot = get_active_slot();
1149
	slot->results = &results;
1150
	curl_setup_http(slot->curl, url, DAV_PROPFIND,
1151
			&out_buffer, fwrite_buffer);
1152
	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1153
	curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer);
1154

1155
	if (start_active_slot(slot)) {
1156
		run_active_slot(slot);
1157
		if (results.curl_result == CURLE_OK) {
1158
			XML_Parser parser = XML_ParserCreate(NULL);
1159
			enum XML_Status result;
1160
			ctx.name = xcalloc(10, 1);
1161
			ctx.len = 0;
1162
			ctx.cdata = NULL;
1163
			ctx.userFunc = handle_remote_ls_ctx;
1164
			ctx.userData = &ls;
1165
			XML_SetUserData(parser, &ctx);
1166
			XML_SetElementHandler(parser, xml_start_tag,
1167
					      xml_end_tag);
1168
			XML_SetCharacterDataHandler(parser, xml_cdata);
1169
			result = XML_Parse(parser, in_buffer.buf,
1170
					   in_buffer.len, 1);
1171
			free(ctx.name);
1172

1173
			if (result != XML_STATUS_OK) {
1174
				fprintf(stderr, "XML error: %s\n",
1175
					XML_ErrorString(
1176
						XML_GetErrorCode(parser)));
1177
			}
1178
			XML_ParserFree(parser);
1179
		}
1180
	} else {
1181
		fprintf(stderr, "Unable to start PROPFIND request\n");
1182
	}
1183

1184
	free(ls.path);
1185
	free(url);
1186
	strbuf_release(&out_buffer.buf);
1187
	strbuf_release(&in_buffer);
1188
	curl_slist_free_all(dav_headers);
1189
}
1190

1191
static void get_remote_object_list(unsigned char parent)
1192
{
1193
	char path[] = "objects/XX/";
1194
	static const char hex[] = "0123456789abcdef";
1195
	unsigned int val = parent;
1196

1197
	path[8] = hex[val >> 4];
1198
	path[9] = hex[val & 0xf];
1199
	remote_dir_exists[val] = 0;
1200
	remote_ls(path, (PROCESS_FILES | PROCESS_DIRS),
1201
		  process_ls_object, &val);
1202
}
1203

1204
static int locking_available(void)
1205
{
1206
	struct active_request_slot *slot;
1207
	struct slot_results results;
1208
	struct strbuf in_buffer = STRBUF_INIT;
1209
	struct buffer out_buffer = { STRBUF_INIT, 0 };
1210
	struct curl_slist *dav_headers = http_copy_default_headers();
1211
	struct xml_ctx ctx;
1212
	int lock_flags = 0;
1213
	char *escaped;
1214

1215
	escaped = xml_entities(repo->url);
1216
	strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, escaped);
1217
	free(escaped);
1218

1219
	dav_headers = curl_slist_append(dav_headers, "Depth: 0");
1220
	dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1221

1222
	slot = get_active_slot();
1223
	slot->results = &results;
1224
	curl_setup_http(slot->curl, repo->url, DAV_PROPFIND,
1225
			&out_buffer, fwrite_buffer);
1226
	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1227
	curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer);
1228

1229
	if (start_active_slot(slot)) {
1230
		run_active_slot(slot);
1231
		if (results.curl_result == CURLE_OK) {
1232
			XML_Parser parser = XML_ParserCreate(NULL);
1233
			enum XML_Status result;
1234
			ctx.name = xcalloc(10, 1);
1235
			ctx.len = 0;
1236
			ctx.cdata = NULL;
1237
			ctx.userFunc = handle_lockprop_ctx;
1238
			ctx.userData = &lock_flags;
1239
			XML_SetUserData(parser, &ctx);
1240
			XML_SetElementHandler(parser, xml_start_tag,
1241
					      xml_end_tag);
1242
			result = XML_Parse(parser, in_buffer.buf,
1243
					   in_buffer.len, 1);
1244
			free(ctx.name);
1245

1246
			if (result != XML_STATUS_OK) {
1247
				fprintf(stderr, "XML error: %s\n",
1248
					XML_ErrorString(
1249
						XML_GetErrorCode(parser)));
1250
				lock_flags = 0;
1251
			}
1252
			XML_ParserFree(parser);
1253
			if (!lock_flags)
1254
				error("no DAV locking support on %s",
1255
				      repo->url);
1256

1257
		} else {
1258
			error("Cannot access URL %s, return code %d",
1259
			      repo->url, results.curl_result);
1260
			lock_flags = 0;
1261
		}
1262
	} else {
1263
		error("Unable to start PROPFIND request on %s", repo->url);
1264
	}
1265

1266
	strbuf_release(&out_buffer.buf);
1267
	strbuf_release(&in_buffer);
1268
	curl_slist_free_all(dav_headers);
1269

1270
	return lock_flags;
1271
}
1272

1273
static struct object_list **add_one_object(struct object *obj, struct object_list **p)
1274
{
1275
	struct object_list *entry = xmalloc(sizeof(struct object_list));
1276
	entry->item = obj;
1277
	entry->next = *p;
1278
	*p = entry;
1279
	return &entry->next;
1280
}
1281

1282
static struct object_list **process_blob(struct blob *blob,
1283
					 struct object_list **p)
1284
{
1285
	struct object *obj = &blob->object;
1286

1287
	obj->flags |= LOCAL;
1288

1289
	if (obj->flags & (UNINTERESTING | SEEN))
1290
		return p;
1291

1292
	obj->flags |= SEEN;
1293
	return add_one_object(obj, p);
1294
}
1295

1296
static struct object_list **process_tree(struct tree *tree,
1297
					 struct object_list **p)
1298
{
1299
	struct object *obj = &tree->object;
1300
	struct tree_desc desc;
1301
	struct name_entry entry;
1302

1303
	obj->flags |= LOCAL;
1304

1305
	if (obj->flags & (UNINTERESTING | SEEN))
1306
		return p;
1307
	if (parse_tree(tree) < 0)
1308
		die("bad tree object %s", oid_to_hex(&obj->oid));
1309

1310
	obj->flags |= SEEN;
1311
	p = add_one_object(obj, p);
1312

1313
	init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
1314

1315
	while (tree_entry(&desc, &entry))
1316
		switch (object_type(entry.mode)) {
1317
		case OBJ_TREE:
1318
			p = process_tree(lookup_tree(the_repository, &entry.oid),
1319
					 p);
1320
			break;
1321
		case OBJ_BLOB:
1322
			p = process_blob(lookup_blob(the_repository, &entry.oid),
1323
					 p);
1324
			break;
1325
		default:
1326
			/* Subproject commit - not in this repository */
1327
			break;
1328
		}
1329

1330
	free_tree_buffer(tree);
1331
	return p;
1332
}
1333

1334
static int get_delta(struct rev_info *revs, struct remote_lock *lock)
1335
{
1336
	int i;
1337
	struct commit *commit;
1338
	struct object_list **p = &objects;
1339
	int count = 0;
1340

1341
	while ((commit = get_revision(revs)) != NULL) {
1342
		p = process_tree(repo_get_commit_tree(the_repository, commit),
1343
				 p);
1344
		commit->object.flags |= LOCAL;
1345
		if (!(commit->object.flags & UNINTERESTING))
1346
			count += add_send_request(&commit->object, lock);
1347
	}
1348

1349
	for (i = 0; i < revs->pending.nr; i++) {
1350
		struct object_array_entry *entry = revs->pending.objects + i;
1351
		struct object *obj = entry->item;
1352
		const char *name = entry->name;
1353

1354
		if (obj->flags & (UNINTERESTING | SEEN))
1355
			continue;
1356
		if (obj->type == OBJ_TAG) {
1357
			obj->flags |= SEEN;
1358
			p = add_one_object(obj, p);
1359
			continue;
1360
		}
1361
		if (obj->type == OBJ_TREE) {
1362
			p = process_tree((struct tree *)obj, p);
1363
			continue;
1364
		}
1365
		if (obj->type == OBJ_BLOB) {
1366
			p = process_blob((struct blob *)obj, p);
1367
			continue;
1368
		}
1369
		die("unknown pending object %s (%s)", oid_to_hex(&obj->oid), name);
1370
	}
1371

1372
	while (objects) {
1373
		if (!(objects->item->flags & UNINTERESTING))
1374
			count += add_send_request(objects->item, lock);
1375
		objects = objects->next;
1376
	}
1377

1378
	return count;
1379
}
1380

1381
static int update_remote(const struct object_id *oid, struct remote_lock *lock)
1382
{
1383
	struct active_request_slot *slot;
1384
	struct slot_results results;
1385
	struct buffer out_buffer = { STRBUF_INIT, 0 };
1386
	struct curl_slist *dav_headers;
1387

1388
	dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF);
1389

1390
	strbuf_addf(&out_buffer.buf, "%s\n", oid_to_hex(oid));
1391

1392
	slot = get_active_slot();
1393
	slot->results = &results;
1394
	curl_setup_http(slot->curl, lock->url, DAV_PUT,
1395
			&out_buffer, fwrite_null);
1396
	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1397

1398
	if (start_active_slot(slot)) {
1399
		run_active_slot(slot);
1400
		strbuf_release(&out_buffer.buf);
1401
		if (results.curl_result != CURLE_OK) {
1402
			fprintf(stderr,
1403
				"PUT error: curl result=%d, HTTP code=%ld\n",
1404
				results.curl_result, results.http_code);
1405
			/* We should attempt recovery? */
1406
			return 0;
1407
		}
1408
	} else {
1409
		strbuf_release(&out_buffer.buf);
1410
		fprintf(stderr, "Unable to start PUT request\n");
1411
		return 0;
1412
	}
1413

1414
	return 1;
1415
}
1416

1417
static struct ref *remote_refs;
1418

1419
static void one_remote_ref(const char *refname)
1420
{
1421
	struct ref *ref;
1422
	struct object *obj;
1423

1424
	ref = alloc_ref(refname);
1425

1426
	if (http_fetch_ref(repo->url, ref) != 0) {
1427
		fprintf(stderr,
1428
			"Unable to fetch ref %s from %s\n",
1429
			refname, repo->url);
1430
		free(ref);
1431
		return;
1432
	}
1433

1434
	/*
1435
	 * Fetch a copy of the object if it doesn't exist locally - it
1436
	 * may be required for updating server info later.
1437
	 */
1438
	if (repo->can_update_info_refs && !repo_has_object_file(the_repository, &ref->old_oid)) {
1439
		obj = lookup_unknown_object(the_repository, &ref->old_oid);
1440
		fprintf(stderr,	"  fetch %s for %s\n",
1441
			oid_to_hex(&ref->old_oid), refname);
1442
		add_fetch_request(obj);
1443
	}
1444

1445
	ref->next = remote_refs;
1446
	remote_refs = ref;
1447
}
1448

1449
static void get_dav_remote_heads(void)
1450
{
1451
	remote_ls("refs/", (PROCESS_FILES | PROCESS_DIRS | RECURSIVE), process_ls_ref, NULL);
1452
}
1453

1454
static void add_remote_info_ref(struct remote_ls_ctx *ls)
1455
{
1456
	struct strbuf *buf = (struct strbuf *)ls->userData;
1457
	struct object *o;
1458
	struct ref *ref;
1459

1460
	ref = alloc_ref(ls->dentry_name);
1461

1462
	if (http_fetch_ref(repo->url, ref) != 0) {
1463
		fprintf(stderr,
1464
			"Unable to fetch ref %s from %s\n",
1465
			ls->dentry_name, repo->url);
1466
		aborted = 1;
1467
		free(ref);
1468
		return;
1469
	}
1470

1471
	o = parse_object(the_repository, &ref->old_oid);
1472
	if (!o) {
1473
		fprintf(stderr,
1474
			"Unable to parse object %s for remote ref %s\n",
1475
			oid_to_hex(&ref->old_oid), ls->dentry_name);
1476
		aborted = 1;
1477
		free(ref);
1478
		return;
1479
	}
1480

1481
	strbuf_addf(buf, "%s\t%s\n",
1482
		    oid_to_hex(&ref->old_oid), ls->dentry_name);
1483

1484
	if (o->type == OBJ_TAG) {
1485
		o = deref_tag(the_repository, o, ls->dentry_name, 0);
1486
		if (o)
1487
			strbuf_addf(buf, "%s\t%s^{}\n",
1488
				    oid_to_hex(&o->oid), ls->dentry_name);
1489
	}
1490
	free(ref);
1491
}
1492

1493
static void update_remote_info_refs(struct remote_lock *lock)
1494
{
1495
	struct buffer buffer = { STRBUF_INIT, 0 };
1496
	struct active_request_slot *slot;
1497
	struct slot_results results;
1498
	struct curl_slist *dav_headers;
1499

1500
	remote_ls("refs/", (PROCESS_FILES | RECURSIVE),
1501
		  add_remote_info_ref, &buffer.buf);
1502
	if (!aborted) {
1503
		dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF);
1504

1505
		slot = get_active_slot();
1506
		slot->results = &results;
1507
		curl_setup_http(slot->curl, lock->url, DAV_PUT,
1508
				&buffer, fwrite_null);
1509
		curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1510

1511
		if (start_active_slot(slot)) {
1512
			run_active_slot(slot);
1513
			if (results.curl_result != CURLE_OK) {
1514
				fprintf(stderr,
1515
					"PUT error: curl result=%d, HTTP code=%ld\n",
1516
					results.curl_result, results.http_code);
1517
			}
1518
		}
1519
	}
1520
	strbuf_release(&buffer.buf);
1521
}
1522

1523
static int remote_exists(const char *path)
1524
{
1525
	char *url = xstrfmt("%s%s", repo->url, path);
1526
	int ret;
1527

1528

1529
	switch (http_get_strbuf(url, NULL, NULL)) {
1530
	case HTTP_OK:
1531
		ret = 1;
1532
		break;
1533
	case HTTP_MISSING_TARGET:
1534
		ret = 0;
1535
		break;
1536
	case HTTP_ERROR:
1537
		error("unable to access '%s': %s", url, curl_errorstr);
1538
		/* fallthrough */
1539
	default:
1540
		ret = -1;
1541
	}
1542
	free(url);
1543
	return ret;
1544
}
1545

1546
static void fetch_symref(const char *path, char **symref, struct object_id *oid)
1547
{
1548
	char *url = xstrfmt("%s%s", repo->url, path);
1549
	struct strbuf buffer = STRBUF_INIT;
1550
	const char *name;
1551

1552
	if (http_get_strbuf(url, &buffer, NULL) != HTTP_OK)
1553
		die("Couldn't get %s for remote symref\n%s", url,
1554
		    curl_errorstr);
1555
	free(url);
1556

1557
	FREE_AND_NULL(*symref);
1558
	oidclr(oid, the_repository->hash_algo);
1559

1560
	if (buffer.len == 0)
1561
		return;
1562

1563
	/* Cut off trailing newline. */
1564
	strbuf_rtrim(&buffer);
1565

1566
	/* If it's a symref, set the refname; otherwise try for a sha1 */
1567
	if (skip_prefix(buffer.buf, "ref: ", &name)) {
1568
		*symref = xmemdupz(name, buffer.len - (name - buffer.buf));
1569
	} else {
1570
		get_oid_hex(buffer.buf, oid);
1571
	}
1572

1573
	strbuf_release(&buffer);
1574
}
1575

1576
static int verify_merge_base(struct object_id *head_oid, struct ref *remote)
1577
{
1578
	struct commit *head = lookup_commit_or_die(head_oid, "HEAD");
1579
	struct commit *branch = lookup_commit_or_die(&remote->old_oid,
1580
						     remote->name);
1581
	int ret = repo_in_merge_bases(the_repository, branch, head);
1582

1583
	if (ret < 0)
1584
		exit(128);
1585
	return ret;
1586
}
1587

1588
static int delete_remote_branch(const char *pattern, int force)
1589
{
1590
	struct ref *refs = remote_refs;
1591
	struct ref *remote_ref = NULL;
1592
	struct object_id head_oid;
1593
	char *symref = NULL;
1594
	int match;
1595
	int patlen = strlen(pattern);
1596
	int i;
1597
	struct active_request_slot *slot;
1598
	struct slot_results results;
1599
	char *url;
1600

1601
	/* Find the remote branch(es) matching the specified branch name */
1602
	for (match = 0; refs; refs = refs->next) {
1603
		char *name = refs->name;
1604
		int namelen = strlen(name);
1605
		if (namelen < patlen ||
1606
		    memcmp(name + namelen - patlen, pattern, patlen))
1607
			continue;
1608
		if (namelen != patlen && name[namelen - patlen - 1] != '/')
1609
			continue;
1610
		match++;
1611
		remote_ref = refs;
1612
	}
1613
	if (match == 0)
1614
		return error("No remote branch matches %s", pattern);
1615
	if (match != 1)
1616
		return error("More than one remote branch matches %s",
1617
			     pattern);
1618

1619
	/*
1620
	 * Remote HEAD must be a symref (not exactly foolproof; a remote
1621
	 * symlink to a symref will look like a symref)
1622
	 */
1623
	fetch_symref("HEAD", &symref, &head_oid);
1624
	if (!symref)
1625
		return error("Remote HEAD is not a symref");
1626

1627
	/* Remote branch must not be the remote HEAD */
1628
	for (i = 0; symref && i < MAXDEPTH; i++) {
1629
		if (!strcmp(remote_ref->name, symref))
1630
			return error("Remote branch %s is the current HEAD",
1631
				     remote_ref->name);
1632
		fetch_symref(symref, &symref, &head_oid);
1633
	}
1634

1635
	/* Run extra sanity checks if delete is not forced */
1636
	if (!force) {
1637
		/* Remote HEAD must resolve to a known object */
1638
		if (symref)
1639
			return error("Remote HEAD symrefs too deep");
1640
		if (is_null_oid(&head_oid))
1641
			return error("Unable to resolve remote HEAD");
1642
		if (!repo_has_object_file(the_repository, &head_oid))
1643
			return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", oid_to_hex(&head_oid));
1644

1645
		/* Remote branch must resolve to a known object */
1646
		if (is_null_oid(&remote_ref->old_oid))
1647
			return error("Unable to resolve remote branch %s",
1648
				     remote_ref->name);
1649
		if (!repo_has_object_file(the_repository, &remote_ref->old_oid))
1650
			return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, oid_to_hex(&remote_ref->old_oid));
1651

1652
		/* Remote branch must be an ancestor of remote HEAD */
1653
		if (!verify_merge_base(&head_oid, remote_ref)) {
1654
			return error("The branch '%s' is not an ancestor "
1655
				     "of your current HEAD.\n"
1656
				     "If you are sure you want to delete it,"
1657
				     " run:\n\t'git http-push -D %s %s'",
1658
				     remote_ref->name, repo->url, pattern);
1659
		}
1660
	}
1661

1662
	/* Send delete request */
1663
	fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name);
1664
	if (dry_run)
1665
		return 0;
1666
	url = xstrfmt("%s%s", repo->url, remote_ref->name);
1667
	slot = get_active_slot();
1668
	slot->results = &results;
1669
	curl_setup_http_get(slot->curl, url, DAV_DELETE);
1670
	if (start_active_slot(slot)) {
1671
		run_active_slot(slot);
1672
		free(url);
1673
		if (results.curl_result != CURLE_OK)
1674
			return error("DELETE request failed (%d/%ld)",
1675
				     results.curl_result, results.http_code);
1676
	} else {
1677
		free(url);
1678
		return error("Unable to start DELETE request");
1679
	}
1680

1681
	return 0;
1682
}
1683

1684
static void run_request_queue(void)
1685
{
1686
	is_running_queue = 1;
1687
	fill_active_slots();
1688
	add_fill_function(NULL, fill_active_slot);
1689
	do {
1690
		finish_all_active_slots();
1691
		fill_active_slots();
1692
	} while (request_queue_head && !aborted);
1693

1694
	is_running_queue = 0;
1695
}
1696

1697
int cmd_main(int argc, const char **argv)
1698
{
1699
	struct transfer_request *request;
1700
	struct transfer_request *next_request;
1701
	struct refspec rs = REFSPEC_INIT_PUSH;
1702
	struct remote_lock *ref_lock = NULL;
1703
	struct remote_lock *info_ref_lock = NULL;
1704
	int delete_branch = 0;
1705
	int force_delete = 0;
1706
	int objects_to_send;
1707
	int rc = 0;
1708
	int i;
1709
	int new_refs;
1710
	struct ref *ref, *local_refs;
1711

1712
	CALLOC_ARRAY(repo, 1);
1713

1714
	argv++;
1715
	for (i = 1; i < argc; i++, argv++) {
1716
		const char *arg = *argv;
1717

1718
		if (*arg == '-') {
1719
			if (!strcmp(arg, "--all")) {
1720
				push_all = MATCH_REFS_ALL;
1721
				continue;
1722
			}
1723
			if (!strcmp(arg, "--force")) {
1724
				force_all = 1;
1725
				continue;
1726
			}
1727
			if (!strcmp(arg, "--dry-run")) {
1728
				dry_run = 1;
1729
				continue;
1730
			}
1731
			if (!strcmp(arg, "--helper-status")) {
1732
				helper_status = 1;
1733
				continue;
1734
			}
1735
			if (!strcmp(arg, "--verbose")) {
1736
				push_verbosely = 1;
1737
				http_is_verbose = 1;
1738
				continue;
1739
			}
1740
			if (!strcmp(arg, "-d")) {
1741
				delete_branch = 1;
1742
				continue;
1743
			}
1744
			if (!strcmp(arg, "-D")) {
1745
				delete_branch = 1;
1746
				force_delete = 1;
1747
				continue;
1748
			}
1749
			if (!strcmp(arg, "-h"))
1750
				usage(http_push_usage);
1751
		}
1752
		if (!repo->url) {
1753
			char *path = strstr(arg, "//");
1754
			str_end_url_with_slash(arg, &repo->url);
1755
			repo->path_len = strlen(repo->url);
1756
			if (path) {
1757
				repo->path = strchr(path+2, '/');
1758
				if (repo->path)
1759
					repo->path_len = strlen(repo->path);
1760
			}
1761
			continue;
1762
		}
1763
		refspec_appendn(&rs, argv, argc - i);
1764
		break;
1765
	}
1766

1767
	if (!repo->url)
1768
		usage(http_push_usage);
1769

1770
	if (delete_branch && rs.nr != 1)
1771
		die("You must specify only one branch name when deleting a remote branch");
1772

1773
	setup_git_directory();
1774

1775
	memset(remote_dir_exists, -1, 256);
1776

1777
	http_init(NULL, repo->url, 1);
1778

1779
	is_running_queue = 0;
1780

1781
	/* Verify DAV compliance/lock support */
1782
	if (!locking_available()) {
1783
		rc = 1;
1784
		goto cleanup;
1785
	}
1786

1787
	sigchain_push_common(remove_locks_on_signal);
1788

1789
	/* Check whether the remote has server info files */
1790
	repo->can_update_info_refs = 0;
1791
	repo->has_info_refs = remote_exists("info/refs");
1792
	repo->has_info_packs = remote_exists("objects/info/packs");
1793
	if (repo->has_info_refs) {
1794
		info_ref_lock = lock_remote("info/refs", LOCK_TIME);
1795
		if (info_ref_lock)
1796
			repo->can_update_info_refs = 1;
1797
		else {
1798
			error("cannot lock existing info/refs");
1799
			rc = 1;
1800
			goto cleanup;
1801
		}
1802
	}
1803
	if (repo->has_info_packs)
1804
		fetch_indices();
1805

1806
	/* Get a list of all local and remote heads to validate refspecs */
1807
	local_refs = get_local_heads();
1808
	fprintf(stderr, "Fetching remote heads...\n");
1809
	get_dav_remote_heads();
1810
	run_request_queue();
1811

1812
	/* Remove a remote branch if -d or -D was specified */
1813
	if (delete_branch) {
1814
		const char *branch = rs.items[i].src;
1815
		if (delete_remote_branch(branch, force_delete) == -1) {
1816
			fprintf(stderr, "Unable to delete remote branch %s\n",
1817
				branch);
1818
			if (helper_status)
1819
				printf("error %s cannot remove\n", branch);
1820
		}
1821
		goto cleanup;
1822
	}
1823

1824
	/* match them up */
1825
	if (match_push_refs(local_refs, &remote_refs, &rs, push_all)) {
1826
		rc = -1;
1827
		goto cleanup;
1828
	}
1829
	if (!remote_refs) {
1830
		fprintf(stderr, "No refs in common and none specified; doing nothing.\n");
1831
		if (helper_status)
1832
			printf("error null no match\n");
1833
		rc = 0;
1834
		goto cleanup;
1835
	}
1836

1837
	new_refs = 0;
1838
	for (ref = remote_refs; ref; ref = ref->next) {
1839
		struct rev_info revs;
1840
		struct strvec commit_argv = STRVEC_INIT;
1841

1842
		if (!ref->peer_ref)
1843
			continue;
1844

1845
		if (is_null_oid(&ref->peer_ref->new_oid)) {
1846
			if (delete_remote_branch(ref->name, 1) == -1) {
1847
				error("Could not remove %s", ref->name);
1848
				if (helper_status)
1849
					printf("error %s cannot remove\n", ref->name);
1850
				rc = -4;
1851
			}
1852
			else if (helper_status)
1853
				printf("ok %s\n", ref->name);
1854
			new_refs++;
1855
			continue;
1856
		}
1857

1858
		if (oideq(&ref->old_oid, &ref->peer_ref->new_oid)) {
1859
			if (push_verbosely)
1860
				/* stable plumbing output; do not modify or localize */
1861
				fprintf(stderr, "'%s': up-to-date\n", ref->name);
1862
			if (helper_status)
1863
				printf("ok %s up to date\n", ref->name);
1864
			continue;
1865
		}
1866

1867
		if (!force_all &&
1868
		    !is_null_oid(&ref->old_oid) &&
1869
		    !ref->force) {
1870
			if (!repo_has_object_file(the_repository, &ref->old_oid) ||
1871
			    !ref_newer(&ref->peer_ref->new_oid,
1872
				       &ref->old_oid)) {
1873
				/*
1874
				 * We do not have the remote ref, or
1875
				 * we know that the remote ref is not
1876
				 * an ancestor of what we are trying to
1877
				 * push.  Either way this can be losing
1878
				 * commits at the remote end and likely
1879
				 * we were not up to date to begin with.
1880
				 */
1881
				/* stable plumbing output; do not modify or localize */
1882
				error("remote '%s' is not an ancestor of\n"
1883
				      "local '%s'.\n"
1884
				      "Maybe you are not up-to-date and "
1885
				      "need to pull first?",
1886
				      ref->name,
1887
				      ref->peer_ref->name);
1888
				if (helper_status)
1889
					printf("error %s non-fast forward\n", ref->name);
1890
				rc = -2;
1891
				continue;
1892
			}
1893
		}
1894
		oidcpy(&ref->new_oid, &ref->peer_ref->new_oid);
1895
		new_refs++;
1896

1897
		fprintf(stderr, "updating '%s'", ref->name);
1898
		if (strcmp(ref->name, ref->peer_ref->name))
1899
			fprintf(stderr, " using '%s'", ref->peer_ref->name);
1900
		fprintf(stderr, "\n  from %s\n  to   %s\n",
1901
			oid_to_hex(&ref->old_oid), oid_to_hex(&ref->new_oid));
1902
		if (dry_run) {
1903
			if (helper_status)
1904
				printf("ok %s\n", ref->name);
1905
			continue;
1906
		}
1907

1908
		/* Lock remote branch ref */
1909
		ref_lock = lock_remote(ref->name, LOCK_TIME);
1910
		if (!ref_lock) {
1911
			fprintf(stderr, "Unable to lock remote branch %s\n",
1912
				ref->name);
1913
			if (helper_status)
1914
				printf("error %s lock error\n", ref->name);
1915
			rc = 1;
1916
			continue;
1917
		}
1918

1919
		/* Set up revision info for this refspec */
1920
		strvec_push(&commit_argv, ""); /* ignored */
1921
		strvec_push(&commit_argv, "--objects");
1922
		strvec_push(&commit_argv, oid_to_hex(&ref->new_oid));
1923
		if (!push_all && !is_null_oid(&ref->old_oid))
1924
			strvec_pushf(&commit_argv, "^%s",
1925
				     oid_to_hex(&ref->old_oid));
1926
		repo_init_revisions(the_repository, &revs, setup_git_directory());
1927
		setup_revisions(commit_argv.nr, commit_argv.v, &revs, NULL);
1928
		revs.edge_hint = 0; /* just in case */
1929

1930
		/* Generate a list of objects that need to be pushed */
1931
		pushing = 0;
1932
		if (prepare_revision_walk(&revs))
1933
			die("revision walk setup failed");
1934
		mark_edges_uninteresting(&revs, NULL, 0);
1935
		objects_to_send = get_delta(&revs, ref_lock);
1936
		finish_all_active_slots();
1937

1938
		/* Push missing objects to remote, this would be a
1939
		   convenient time to pack them first if appropriate. */
1940
		pushing = 1;
1941
		if (objects_to_send)
1942
			fprintf(stderr, "    sending %d objects\n",
1943
				objects_to_send);
1944

1945
		run_request_queue();
1946

1947
		/* Update the remote branch if all went well */
1948
		if (aborted || !update_remote(&ref->new_oid, ref_lock))
1949
			rc = 1;
1950

1951
		if (!rc)
1952
			fprintf(stderr, "    done\n");
1953
		if (helper_status)
1954
			printf("%s %s\n", !rc ? "ok" : "error", ref->name);
1955
		unlock_remote(ref_lock);
1956
		check_locks();
1957
		strvec_clear(&commit_argv);
1958
		release_revisions(&revs);
1959
	}
1960

1961
	/* Update remote server info if appropriate */
1962
	if (repo->has_info_refs && new_refs) {
1963
		if (info_ref_lock && repo->can_update_info_refs) {
1964
			fprintf(stderr, "Updating remote server info\n");
1965
			if (!dry_run)
1966
				update_remote_info_refs(info_ref_lock);
1967
		} else {
1968
			fprintf(stderr, "Unable to update server info\n");
1969
		}
1970
	}
1971

1972
 cleanup:
1973
	if (info_ref_lock)
1974
		unlock_remote(info_ref_lock);
1975
	free(repo);
1976

1977
	http_cleanup();
1978

1979
	request = request_queue_head;
1980
	while (request != NULL) {
1981
		next_request = request->next;
1982
		release_request(request);
1983
		request = next_request;
1984
	}
1985

1986
	return rc;
1987
}
1988

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.