forked from git/git
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconnected.c
More file actions
Latest commit
119 lines (107 loc) · 3.22 KB
/
Copy pathconnected.c
File metadata and controls
119 lines (107 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include"cache.h"
#include"run-command.h"
#include"sigchain.h"
#include"connected.h"
#include"transport.h"
intcheck_everything_connected(sha1_iterate_fnfn, intquiet, void*cb_data)
{
returncheck_everything_connected_with_transport(fn, quiet, cb_data, NULL);
}
/*
* If we feed all the commits we want to verify to this command
*
* $ git rev-list --objects --stdin --not --all
*
* and if it does not error out, that means everything reachable from
* these commits locally exists and is connected to our existing refs.
* Note that this does _not_ validate the individual objects.
*
* Returns 0 if everything is connected, non-zero otherwise.
*/
staticintcheck_everything_connected_real(sha1_iterate_fnfn,
intquiet,
void*cb_data,
structtransport*transport,
constchar*shallow_file)
{
structchild_processrev_list=CHILD_PROCESS_INIT;
constchar*argv[9];
charcommit[41];
unsigned charsha1[20];
interr=0, ac=0;
structpacked_git*new_pack=NULL;
size_tbase_len;
if (fn(cb_data, sha1))
returnerr;
if (transport&&transport->smart_options&&
transport->smart_options->self_contained_and_connected&&
transport->pack_lockfile&&
strip_suffix(transport->pack_lockfile, ".keep", &base_len)) {
structstrbufidx_file=STRBUF_INIT;
strbuf_add(&idx_file, transport->pack_lockfile, base_len);
strbuf_addstr(&idx_file, ".idx");
new_pack=add_packed_git(idx_file.buf, idx_file.len, 1);
strbuf_release(&idx_file);
}
if (shallow_file) {
argv[ac++] ="--shallow-file";
argv[ac++] =shallow_file;
}
argv[ac++] ="rev-list";
argv[ac++] ="--objects";
argv[ac++] ="--stdin";
argv[ac++] ="--not";
argv[ac++] ="--all";
if (quiet)
argv[ac++] ="--quiet";
argv[ac] =NULL;
rev_list.argv=argv;
rev_list.git_cmd=1;
rev_list.in=-1;
rev_list.no_stdout=1;
rev_list.no_stderr=quiet;
if (start_command(&rev_list))
returnerror(_("Could not run 'git rev-list'"));
sigchain_push(SIGPIPE, SIG_IGN);
commit[40] ='\n';
do {
/*
* If index-pack already checked that:
* - there are no dangling pointers in the new pack
* - the pack is self contained
* Then if the updated ref is in the new pack, then we
* are sure the ref is good and not sending it to
* rev-list for verification.
*/
if (new_pack&&find_pack_entry_one(sha1, new_pack))
continue;
memcpy(commit, sha1_to_hex(sha1), 40);
if (write_in_full(rev_list.in, commit, 41) <0) {
if (errno!=EPIPE&&errno!=EINVAL)
error(_("failed write to rev-list: %s"),
strerror(errno));
err=-1;
break;
}
} while (!fn(cb_data, sha1));
if (close(rev_list.in)) {
error(_("failed to close rev-list's stdin: %s"), strerror(errno));
err=-1;
}
sigchain_pop(SIGPIPE);
returnfinish_command(&rev_list) ||err;
}
intcheck_everything_connected_with_transport(sha1_iterate_fnfn,
intquiet,
void*cb_data,
structtransport*transport)
{
returncheck_everything_connected_real(fn, quiet, cb_data,
transport, NULL);
}
intcheck_shallow_connected(sha1_iterate_fnfn, intquiet, void*cb_data,
constchar*shallow_file)
{
returncheck_everything_connected_real(fn, quiet, cb_data,
NULL, shallow_file);
}