Skip to content
Open

Jch #2105

Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
fb78702
refs: avoid "too many arguments"
gitster Aug 6, 2024
becacd2
cat-file: avoid "too many arguments"
gitster Aug 6, 2024
2446e8f
notes: avoid "too many arguments"
gitster Aug 6, 2024
6c8ee88
miscellaneous: avoid "too many arguments"
gitster Aug 6, 2024
1e77bf0
packfile: move sizep computation
peff Aug 23, 2024
117addc
packfile: allow content-limit for cat-file
peff Aug 23, 2024
b2df0c0
packfile: fix off-by-one in content_limit comparison
Aug 23, 2024
a5f683f
packfile: inline cache_or_unpack_entry
Aug 23, 2024
98521d6
cat-file: use delta_base_cache entries directly
Aug 23, 2024
28402bc
packfile: packed_object_info avoids packed_to_object_type
Aug 23, 2024
7d4e4d5
object_info: content_limit only applies to blobs
Aug 23, 2024
489810f
cat-file: batch-command uses content_limit
Aug 23, 2024
1732dda
cat-file: batch_write: use size_t for length
Aug 23, 2024
f043683
cat-file: use writev(2) if available
Aug 23, 2024
31c5b4b
version: refactor strbuf_sanitize()
chriscool Sep 10, 2024
8afd0ee
strbuf: refactor strbuf_trim_trailing_ch()
chriscool Sep 10, 2024
3cb155a
Add 'promisor-remote' capability to protocol v2
chriscool Sep 10, 2024
bc0c4e1
promisor-remote: check advertised name or URL
chriscool Sep 10, 2024
82d283c
t7500: make each piece more independent
gitster Oct 14, 2024
dbafaff
config: values of pathname type can be prefixed with :(optional)
gitster Oct 14, 2024
2da08f2
parseopt: values of pathname type can be prefixed with :(optional)
gitster Oct 14, 2024
bed4d80
builtin/ls-remote: plug leaking server options
pks-t Oct 21, 2024
bfac141
t/helper: fix leaks in "reach" test tool
pks-t Oct 21, 2024
f4bb632
grep: fix leak in `grep_splice_or()`
pks-t Oct 21, 2024
4042f03
builtin/grep: fix leak with `--max-count=0`
pks-t Oct 21, 2024
ab28bc8
revision: fix leaking bloom filters
pks-t Oct 21, 2024
27a1c1f
diff-lib: fix leaking diffopts in `do_diff_cache()`
pks-t Oct 21, 2024
c0a1026
pretty: clear signature check
pks-t Oct 21, 2024
5ca4de4
upload-pack: fix leaking URI protocols
pks-t Oct 21, 2024
27164f7
builtin/commit: fix leaking change data contents
pks-t Oct 21, 2024
ecbb58e
trailer: fix leaking trailer values
pks-t Oct 21, 2024
9d0482d
trailer: fix leaking strbufs when formatting trailers
pks-t Oct 21, 2024
06d6581
builtin/commit: fix leaking cleanup config
pks-t Oct 21, 2024
7c66167
transport-helper: fix leaking import/export marks
pks-t Oct 21, 2024
8eded2f
builtin/tag: fix leaking key ID on failure to sign
pks-t Oct 21, 2024
9a2c5b0
combine-diff: fix leaking lost lines
pks-t Oct 21, 2024
8977bcf
dir: release untracked cache data
pks-t Oct 21, 2024
1fe066c
sparse-index: correctly free EWAH contents
pks-t Oct 21, 2024
a4a3b8c
t/helper: stop re-initialization of `the_repository`
pks-t Oct 21, 2024
44cbc97
t/helper: fix leaking buffer in "dump-untracked-cache"
pks-t Oct 21, 2024
e0e970d
dir: fix leak when parsing "status.showUntrackedFiles"
pks-t Oct 21, 2024
3ec42f3
builtin/merge: release outbut buffer after performing merge
pks-t Oct 21, 2024
931847a
list-objects-filter-options: work around reported leak on error
pks-t Oct 21, 2024
e6e6315
reftable/system: move "dir.h" to its only user
pks-t Oct 23, 2024
ac90e9f
reftable: explicitly handle hash format IDs
pks-t Oct 23, 2024
da2d199
reftable/system: stop depending on "hash.h"
pks-t Oct 23, 2024
3c58a50
reftable/stack: stop using `fsync_component()` directly
pks-t Oct 23, 2024
3f5e8d2
reftable/system: provide thin wrapper for tempfile subsystem
pks-t Oct 23, 2024
ec282c1
reftable/stack: drop only use of `get_locked_file_path()`
pks-t Oct 23, 2024
3740325
reftable/system: provide thin wrapper for lockfile subsystem
pks-t Oct 23, 2024
ae0f757
compat/mingw: support POSIX semantics for atomic renames
pks-t Oct 27, 2024
0142990
show-index: fix uninitialized hash function
quanta-kt Oct 26, 2024
2be7127
Documentation/git-bundle.txt: mention full backup example
LemmingAvalanche Oct 29, 2024
4f68a40
Documentation/git-bundle.txt: mention --all in spec. refs
LemmingAvalanche Oct 29, 2024
c4ac5fa
Documentation/git-bundle.txt: discuss naïve backups
LemmingAvalanche Oct 29, 2024
fcae55a
fetch-pack: refactor packet writing
calvin-wan-google Oct 28, 2024
9ddf78d
fetch-pack: move fetch initialization
calvin-wan-google Oct 28, 2024
bc52916
serve: advertise object-info feature
calvin-wan-google Oct 28, 2024
8c4368d
transport: add client support for object-info
calvin-wan-google Oct 28, 2024
f1ffe74
cat-file: add declaration of variable i inside its for loop
peijianju Oct 28, 2024
999bed8
cat-file: add remote-object-info to batch-command
peijianju Oct 28, 2024
d9b67c3
path-walk: introduce an object walk by path
derrickstolee Oct 31, 2024
44425c4
test-lib-functions: add test_cmp_sorted
derrickstolee Oct 31, 2024
35e6cf9
t6601: add helper for testing path-walk API
derrickstolee Oct 31, 2024
ca51c2d
path-walk: allow consumer to specify object types
derrickstolee Oct 31, 2024
8fa5e62
path-walk: visit tags and cached objects
derrickstolee Oct 31, 2024
c99f26c
path-walk: mark trees and blobs as UNINTERESTING
derrickstolee Oct 31, 2024
d18caa1
Merge branch 'kn/arbitrary-suffixes' into jch
ttaylorr Nov 1, 2024
fbed493
Merge branch 'kn/ci-clang-format-tidy' into jch
ttaylorr Nov 1, 2024
46be1b3
Merge branch 'cw/config-extensions' into jch
ttaylorr Nov 1, 2024
1597170
Merge branch 'ps/upgrade-clar' into jch
ttaylorr Nov 1, 2024
5b107fa
###
ttaylorr Nov 1, 2024
ff12b90
Merge branch 'jk/left-right-bitmap' into jch
ttaylorr Nov 1, 2024
8f346e1
### match next
ttaylorr Nov 1, 2024
ce4ffbd
Merge branch 'ej/cat-file-remote-object-info' into jch
ttaylorr Nov 1, 2024
5215bb8
Merge branch 'ps/mingw-rename' into jch
ttaylorr Nov 1, 2024
5640c87
Merge branch 'ps/reftable-detach' into jch
ttaylorr Nov 1, 2024
7be0046
Merge branch 'cc/promisor-remote-capability' into jch
ttaylorr Nov 1, 2024
96e5742
Merge branch 'jc/too-many-arguments' into jch
ttaylorr Nov 1, 2024
04bc973
Merge branch 'ew/cat-file-optim' into jch
ttaylorr Nov 1, 2024
71cf160
Merge branch 'bc/drop-ancient-libcurl-and-perl' into jch
ttaylorr Nov 1, 2024
f0176fb
Merge branch 'jc/optional-path' into jch
ttaylorr Nov 1, 2024
ddedb0e
Merge branch 'ps/leakfixes-part-9' into jch
ttaylorr Nov 1, 2024
2f42bd7
Merge branch 'as/show-index-uninitialized-hash' into jch
ttaylorr Nov 1, 2024
c65c75b
Merge branch 'kh/bundle-docs' into jch
ttaylorr Nov 1, 2024
5212635
Merge branch 'ds/path-walk-1' into jch
ttaylorr Nov 1, 2024
515fd3a
Merge branch 'bc/ancient-ci' into jch
ttaylorr Nov 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Documentation/config/promisor.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
promisor.quiet::
If set to "true" assume `--quiet` when fetching additional
objects for a partial clone.

promisor.advertise::
If set to "true", a server will use the "promisor-remote"
capability, see linkgit:gitprotocol-v2[5], to advertise the
promisor remotes it is using, if it uses some. Default is
"false", which means the "promisor-remote" capability is not
advertised.

promisor.acceptFromServer::
If set to "all", a client will accept all the promisor remotes
a server might advertise using the "promisor-remote"
capability. If set to "knownName" the client will accept
promisor remotes which are already configured on the client
and have the same name as those advertised by the client. This
is not very secure, but could be used in a corporate setup
where servers and clients are trusted to not switch name and
URLs. If set to "knownUrl", the client will accept promisor
remotes which have both the same name and the same URL
configured on the client as the name and URL advertised by the
server. This is more secure than "all" or "knownUrl", so it
should be used if possible instead of those options. Default
is "none", which means no promisor remote advertised by a
server will be accepted. By accepting a promisor remote, the
client agrees that the server might omit objects that are
lazily fetchable from this promisor remote from its responses
to "fetch" and "clone" requests from the client. See
linkgit:gitprotocol-v2[5].
54 changes: 54 additions & 0 deletions Documentation/gitprotocol-v2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,60 @@ retrieving the header from a bundle at the indicated URI, and thus
save themselves and the server(s) the request(s) needed to inspect the
headers of that bundle or bundles.

promisor-remote=<pr-infos>
~~~~~~~~~~~~~~~~~~~~~~~~~~

The server may advertise some promisor remotes it is using or knows
about to a client which may want to use them as its promisor remotes,
instead of this repository. In this case <pr-infos> should be of the
form:

pr-infos = pr-info | pr-infos ";" pr-info

pr-info = "name=" pr-name | "name=" pr-name "," "url=" pr-url

where `pr-name` is the urlencoded name of a promisor remote, and
`pr-url` the urlencoded URL of that promisor remote.

In this case, if the client decides to use one or more promisor
remotes the server advertised, it can reply with
"promisor-remote=<pr-names>" where <pr-names> should be of the form:

pr-names = pr-name | pr-names ";" pr-name

where `pr-name` is the urlencoded name of a promisor remote the server
advertised and the client accepts.

Note that, everywhere in this document, `pr-name` MUST be a valid
remote name, and the ';' and ',' characters MUST be encoded if they
appear in `pr-name` or `pr-url`.

If the server doesn't know any promisor remote that could be good for
a client to use, or prefers a client not to use any promisor remote it
uses or knows about, it shouldn't advertise the "promisor-remote"
capability at all.

In this case, or if the client doesn't want to use any promisor remote
the server advertised, the client shouldn't advertise the
"promisor-remote" capability at all in its reply.

The "promisor.advertise" and "promisor.acceptFromServer" configuration
options can be used on the server and client side respectively to
control what they advertise or accept respectively. See the
documentation of these configuration options for more information.

Note that in the future it would be nice if the "promisor-remote"
protocol capability could be used by the server, when responding to
`git fetch` or `git clone`, to advertise better-connected remotes that
the client can use as promisor remotes, instead of this repository, so
that the client can lazily fetch objects from these other
better-connected remotes. This would require the server to omit in its
response the objects available on the better-connected remotes that
the client has accepted. This hasn't been implemented yet though. So
for now this "promisor-remote" capability is useful only when the
server advertises some promisor remotes it already uses to borrow
objects from.

GIT
---
Part of the linkgit:git[1] suite
9 changes: 9 additions & 0 deletions connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "protocol.h"
#include "alias.h"
#include "bundle-uri.h"
#include "promisor-remote.h"

static char *server_capabilities_v1;
static struct strvec server_capabilities_v2 = STRVEC_INIT;
Expand Down Expand Up @@ -487,6 +488,7 @@ void check_stateless_delimiter(int stateless_rpc,
static void send_capabilities(int fd_out, struct packet_reader *reader)
{
const char *hash_name;
const char *promisor_remote_info;

if (server_supports_v2("agent"))
packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized());
Expand All @@ -500,6 +502,13 @@ static void send_capabilities(int fd_out, struct packet_reader *reader)
} else {
reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
}
if (server_feature_v2("promisor-remote", &promisor_remote_info)) {
char *reply = promisor_remote_reply(promisor_remote_info);
if (reply) {
packet_write_fmt(fd_out, "promisor-remote=%s", reply);
free(reply);
}
}
}

int get_remote_bundle_uri(int fd_out, struct packet_reader *reader,
Expand Down
244 changes: 244 additions & 0 deletions promisor-remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "strvec.h"
#include "packfile.h"
#include "environment.h"
#include "url.h"

struct promisor_remote_config {
struct promisor_remote *promisors;
Expand Down Expand Up @@ -221,6 +222,18 @@ int repo_has_promisor_remote(struct repository *r)
return !!repo_promisor_remote_find(r, NULL);
}

int repo_has_accepted_promisor_remote(struct repository *r)
{
struct promisor_remote *p;

promisor_remote_init(r);

for (p = r->promisor_remote_config->promisors; p; p = p->next)
if (p->accepted)
return 1;
return 0;
}

static int remove_fetched_oids(struct repository *repo,
struct object_id **oids,
int oid_nr, int to_free)
Expand Down Expand Up @@ -292,3 +305,234 @@ void promisor_remote_get_direct(struct repository *repo,
if (to_free)
free(remaining_oids);
}

static int allow_unsanitized(char ch)
{
if (ch == ',' || ch == ';' || ch == '%')
return 0;
return ch > 32 && ch < 127;
}

static void promisor_info_vecs(struct repository *repo,
struct strvec *names,
struct strvec *urls)
{
struct promisor_remote *r;

promisor_remote_init(repo);

for (r = repo->promisor_remote_config->promisors; r; r = r->next) {
char *url;
char *url_key = xstrfmt("remote.%s.url", r->name);

strvec_push(names, r->name);
strvec_push(urls, git_config_get_string(url_key, &url) ? NULL : url);

free(url);
free(url_key);
}
}

char *promisor_remote_info(struct repository *repo)
{
struct strbuf sb = STRBUF_INIT;
int advertise_promisors = 0;
struct strvec names = STRVEC_INIT;
struct strvec urls = STRVEC_INIT;

git_config_get_bool("promisor.advertise", &advertise_promisors);

if (!advertise_promisors)
return NULL;

promisor_info_vecs(repo, &names, &urls);

if (!names.nr)
return NULL;

for (size_t i = 0; i < names.nr; i++) {
if (i)
strbuf_addch(&sb, ';');
strbuf_addstr(&sb, "name=");
strbuf_addstr_urlencode(&sb, names.v[i], allow_unsanitized);
if (urls.v[i]) {
strbuf_addstr(&sb, ",url=");
strbuf_addstr_urlencode(&sb, urls.v[i], allow_unsanitized);
}
}

strbuf_sanitize(&sb);

strvec_clear(&names);
strvec_clear(&urls);

return strbuf_detach(&sb, NULL);
}

/*
* Find first index of 'vec' where there is 'val'. 'val' is compared
* case insensively to the strings in 'vec'. If not found 'vec->nr' is
* returned.
*/
static size_t strvec_find_index(struct strvec *vec, const char *val)
{
for (size_t i = 0; i < vec->nr; i++)
if (!strcasecmp(vec->v[i], val))
return i;
return vec->nr;
}

enum accept_promisor {
ACCEPT_NONE = 0,
ACCEPT_KNOWN_URL,
ACCEPT_KNOWN_NAME,
ACCEPT_ALL
};

static int should_accept_remote(enum accept_promisor accept,
const char *remote_name, const char *remote_url,
struct strvec *names, struct strvec *urls)
{
size_t i;

if (accept == ACCEPT_ALL)
return 1;

i = strvec_find_index(names, remote_name);

if (i >= names->nr)
/* We don't know about that remote */
return 0;

if (accept == ACCEPT_KNOWN_NAME)
return 1;

if (accept != ACCEPT_KNOWN_URL)
BUG("Unhandled 'enum accept_promisor' value '%d'", accept);

if (!strcasecmp(urls->v[i], remote_url))
return 1;

warning(_("known remote named '%s' but with url '%s' instead of '%s'"),
remote_name, urls->v[i], remote_url);

return 0;
}

static void filter_promisor_remote(struct repository *repo,
struct strvec *accepted,
const char *info)
{
struct strbuf **remotes;
char *accept_str;
enum accept_promisor accept = ACCEPT_NONE;
struct strvec names = STRVEC_INIT;
struct strvec urls = STRVEC_INIT;

if (!git_config_get_string("promisor.acceptfromserver", &accept_str)) {
if (!accept_str || !*accept_str || !strcasecmp("None", accept_str))
accept = ACCEPT_NONE;
else if (!strcasecmp("KnownUrl", accept_str))
accept = ACCEPT_KNOWN_URL;
else if (!strcasecmp("KnownName", accept_str))
accept = ACCEPT_KNOWN_NAME;
else if (!strcasecmp("All", accept_str))
accept = ACCEPT_ALL;
else
warning(_("unknown '%s' value for '%s' config option"),
accept_str, "promisor.acceptfromserver");
}

if (accept == ACCEPT_NONE)
return;

if (accept != ACCEPT_ALL)
promisor_info_vecs(repo, &names, &urls);

/* Parse remote info received */

remotes = strbuf_split_str(info, ';', 0);

for (size_t i = 0; remotes[i]; i++) {
struct strbuf **elems;
const char *remote_name = NULL;
const char *remote_url = NULL;
char *decoded_name = NULL;
char *decoded_url = NULL;

strbuf_trim_trailing_ch(remotes[i], ';');
elems = strbuf_split_str(remotes[i]->buf, ',', 0);

for (size_t j = 0; elems[j]; j++) {
int res;
strbuf_trim_trailing_ch(elems[j], ',');
res = skip_prefix(elems[j]->buf, "name=", &remote_name) ||
skip_prefix(elems[j]->buf, "url=", &remote_url);
if (!res)
warning(_("unknown element '%s' from remote info"),
elems[j]->buf);
}

if (remote_name)
decoded_name = url_percent_decode(remote_name);
if (remote_url)
decoded_url = url_percent_decode(remote_url);

if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &names, &urls))
strvec_push(accepted, decoded_name);

strbuf_list_free(elems);
free(decoded_name);
free(decoded_url);
}

free(accept_str);
strvec_clear(&names);
strvec_clear(&urls);
strbuf_list_free(remotes);
}

char *promisor_remote_reply(const char *info)
{
struct strvec accepted = STRVEC_INIT;
struct strbuf reply = STRBUF_INIT;

filter_promisor_remote(the_repository, &accepted, info);

if (!accepted.nr)
return NULL;

for (size_t i = 0; i < accepted.nr; i++) {
if (i)
strbuf_addch(&reply, ';');
strbuf_addstr_urlencode(&reply, accepted.v[i], allow_unsanitized);
}

strvec_clear(&accepted);

return strbuf_detach(&reply, NULL);
}

void mark_promisor_remotes_as_accepted(struct repository *r, const char *remotes)
{
struct strbuf **accepted_remotes = strbuf_split_str(remotes, ';', 0);

for (size_t i = 0; accepted_remotes[i]; i++) {
struct promisor_remote *p;
char *decoded_remote;

strbuf_trim_trailing_ch(accepted_remotes[i], ';');
decoded_remote = url_percent_decode(accepted_remotes[i]->buf);

p = repo_promisor_remote_find(r, decoded_remote);
if (p)
p->accepted = 1;
else
warning(_("accepted promisor remote '%s' not found"),
decoded_remote);

free(decoded_remote);
}

strbuf_list_free(accepted_remotes);
}
Loading