git

Форк
0
/
checkout--worker.c 
147 строк · 4.0 Кб
1
#include "builtin.h"
2
#include "config.h"
3
#include "entry.h"
4
#include "gettext.h"
5
#include "parallel-checkout.h"
6
#include "parse-options.h"
7
#include "pkt-line.h"
8
#include "read-cache-ll.h"
9

10
static void packet_to_pc_item(const char *buffer, int len,
11
			      struct parallel_checkout_item *pc_item)
12
{
13
	const struct pc_item_fixed_portion *fixed_portion;
14
	const char *variant;
15
	char *encoding;
16

17
	if (len < sizeof(struct pc_item_fixed_portion))
18
		BUG("checkout worker received too short item (got %dB, exp %dB)",
19
		    len, (int)sizeof(struct pc_item_fixed_portion));
20

21
	fixed_portion = (struct pc_item_fixed_portion *)buffer;
22

23
	if (len - sizeof(struct pc_item_fixed_portion) !=
24
		fixed_portion->name_len + fixed_portion->working_tree_encoding_len)
25
		BUG("checkout worker received corrupted item");
26

27
	variant = buffer + sizeof(struct pc_item_fixed_portion);
28

29
	/*
30
	 * Note: the main process uses zero length to communicate that the
31
	 * encoding is NULL. There is no use case that requires sending an
32
	 * actual empty string, since convert_attrs() never sets
33
	 * ca.working_tree_enconding to "".
34
	 */
35
	if (fixed_portion->working_tree_encoding_len) {
36
		encoding = xmemdupz(variant,
37
				    fixed_portion->working_tree_encoding_len);
38
		variant += fixed_portion->working_tree_encoding_len;
39
	} else {
40
		encoding = NULL;
41
	}
42

43
	memset(pc_item, 0, sizeof(*pc_item));
44
	pc_item->ce = make_empty_transient_cache_entry(fixed_portion->name_len, NULL);
45
	pc_item->ce->ce_namelen = fixed_portion->name_len;
46
	pc_item->ce->ce_mode = fixed_portion->ce_mode;
47
	memcpy(pc_item->ce->name, variant, pc_item->ce->ce_namelen);
48
	oidcpy(&pc_item->ce->oid, &fixed_portion->oid);
49

50
	pc_item->id = fixed_portion->id;
51
	pc_item->ca.crlf_action = fixed_portion->crlf_action;
52
	pc_item->ca.ident = fixed_portion->ident;
53
	pc_item->ca.working_tree_encoding = encoding;
54
}
55

56
static void report_result(struct parallel_checkout_item *pc_item)
57
{
58
	struct pc_item_result res = { 0 };
59
	size_t size;
60

61
	res.id = pc_item->id;
62
	res.status = pc_item->status;
63

64
	if (pc_item->status == PC_ITEM_WRITTEN) {
65
		res.st = pc_item->st;
66
		size = sizeof(res);
67
	} else {
68
		size = PC_ITEM_RESULT_BASE_SIZE;
69
	}
70

71
	packet_write(1, (const char *)&res, size);
72
}
73

74
/* Free the worker-side malloced data, but not pc_item itself. */
75
static void release_pc_item_data(struct parallel_checkout_item *pc_item)
76
{
77
	free((char *)pc_item->ca.working_tree_encoding);
78
	discard_cache_entry(pc_item->ce);
79
}
80

81
static void worker_loop(struct checkout *state)
82
{
83
	struct parallel_checkout_item *items = NULL;
84
	size_t i, nr = 0, alloc = 0;
85

86
	while (1) {
87
		int len = packet_read(0, packet_buffer, sizeof(packet_buffer),
88
				      0);
89

90
		if (len < 0)
91
			BUG("packet_read() returned negative value");
92
		else if (!len)
93
			break;
94

95
		ALLOC_GROW(items, nr + 1, alloc);
96
		packet_to_pc_item(packet_buffer, len, &items[nr++]);
97
	}
98

99
	for (i = 0; i < nr; i++) {
100
		struct parallel_checkout_item *pc_item = &items[i];
101
		write_pc_item(pc_item, state);
102
		report_result(pc_item);
103
		release_pc_item_data(pc_item);
104
	}
105

106
	packet_flush(1);
107

108
	free(items);
109
}
110

111
static const char * const checkout_worker_usage[] = {
112
	N_("git checkout--worker [<options>]"),
113
	NULL
114
};
115

116
int cmd_checkout__worker(int argc, const char **argv, const char *prefix)
117
{
118
	struct checkout state = CHECKOUT_INIT;
119
	struct option checkout_worker_options[] = {
120
		OPT_STRING(0, "prefix", &state.base_dir, N_("string"),
121
			N_("when creating files, prepend <string>")),
122
		OPT_END()
123
	};
124

125
	if (argc == 2 && !strcmp(argv[1], "-h"))
126
		usage_with_options(checkout_worker_usage,
127
				   checkout_worker_options);
128

129
	git_config(git_default_config, NULL);
130
	argc = parse_options(argc, argv, prefix, checkout_worker_options,
131
			     checkout_worker_usage, 0);
132
	if (argc > 0)
133
		usage_with_options(checkout_worker_usage, checkout_worker_options);
134

135
	if (state.base_dir)
136
		state.base_dir_len = strlen(state.base_dir);
137

138
	/*
139
	 * Setting this on a worker won't actually update the index. We just
140
	 * need to tell the checkout machinery to lstat() the written entries,
141
	 * so that we can send this data back to the main process.
142
	 */
143
	state.refresh_cache = 1;
144

145
	worker_loop(&state);
146
	return 0;
147
}
148

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

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

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

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