2005-08-04 09:15:49 +04:00
|
|
|
#include "cache.h"
|
2017-06-14 21:07:36 +03:00
|
|
|
#include "config.h"
|
2005-10-14 05:57:40 +04:00
|
|
|
#include "tag.h"
|
2005-08-04 09:15:49 +04:00
|
|
|
#include "commit.h"
|
2005-10-14 05:57:40 +04:00
|
|
|
#include "tree.h"
|
|
|
|
#include "blob.h"
|
2006-04-19 22:56:53 +04:00
|
|
|
#include "tree-walk.h"
|
2006-05-17 13:56:09 +04:00
|
|
|
#include "refs.h"
|
2009-09-10 19:25:57 +04:00
|
|
|
#include "remote.h"
|
2015-05-20 00:44:23 +03:00
|
|
|
#include "dir.h"
|
2020-03-30 17:03:46 +03:00
|
|
|
#include "oid-array.h"
|
2017-08-19 01:20:19 +03:00
|
|
|
#include "packfile.h"
|
2018-03-23 20:20:56 +03:00
|
|
|
#include "object-store.h"
|
2018-03-23 20:20:57 +03:00
|
|
|
#include "repository.h"
|
2019-04-16 12:33:36 +03:00
|
|
|
#include "submodule.h"
|
2018-07-12 22:39:35 +03:00
|
|
|
#include "midx.h"
|
2018-07-20 19:33:04 +03:00
|
|
|
#include "commit-reach.h"
|
2005-08-04 09:15:49 +04:00
|
|
|
|
2019-04-16 12:33:29 +03:00
|
|
|
static int get_oid_oneline(struct repository *r, const char *, struct object_id *, struct commit_list *);
|
2010-12-13 06:01:15 +03:00
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
typedef int (*disambiguate_hint_fn)(struct repository *, const struct object_id *, void *);
|
2012-06-21 09:07:36 +04:00
|
|
|
|
|
|
|
struct disambiguate_state {
|
2016-09-26 15:00:04 +03:00
|
|
|
int len; /* length of prefix in hex chars */
|
2017-03-26 19:01:24 +03:00
|
|
|
char hex_pfx[GIT_MAX_HEXSZ + 1];
|
2017-03-26 19:01:33 +03:00
|
|
|
struct object_id bin_pfx;
|
2016-09-26 15:00:04 +03:00
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
struct repository *repo;
|
2012-06-21 09:07:36 +04:00
|
|
|
disambiguate_hint_fn fn;
|
|
|
|
void *cb_data;
|
2017-03-26 19:01:33 +03:00
|
|
|
struct object_id candidate;
|
2012-06-21 09:07:36 +04:00
|
|
|
unsigned candidate_exists:1;
|
|
|
|
unsigned candidate_checked:1;
|
|
|
|
unsigned candidate_ok:1;
|
|
|
|
unsigned disambiguate_fn_used:1;
|
|
|
|
unsigned ambiguous:1;
|
2012-07-04 01:21:59 +04:00
|
|
|
unsigned always_call_fn:1;
|
2012-06-21 09:07:36 +04:00
|
|
|
};
|
|
|
|
|
2017-03-26 19:01:34 +03:00
|
|
|
static void update_candidates(struct disambiguate_state *ds, const struct object_id *current)
|
2012-06-21 09:07:36 +04:00
|
|
|
{
|
2012-07-04 01:21:59 +04:00
|
|
|
if (ds->always_call_fn) {
|
2019-04-16 12:33:23 +03:00
|
|
|
ds->ambiguous = ds->fn(ds->repo, current, ds->cb_data) ? 1 : 0;
|
2012-07-04 01:21:59 +04:00
|
|
|
return;
|
|
|
|
}
|
2012-06-21 09:07:36 +04:00
|
|
|
if (!ds->candidate_exists) {
|
|
|
|
/* this is the first candidate */
|
2017-03-26 19:01:34 +03:00
|
|
|
oidcpy(&ds->candidate, current);
|
2012-06-21 09:07:36 +04:00
|
|
|
ds->candidate_exists = 1;
|
|
|
|
return;
|
convert "oidcmp() == 0" to oideq()
Using the more restrictive oideq() should, in the long run,
give the compiler more opportunities to optimize these
callsites. For now, this conversion should be a complete
noop with respect to the generated code.
The result is also perhaps a little more readable, as it
avoids the "zero is equal" idiom. Since it's so prevalent in
C, I think seasoned programmers tend not to even notice it
anymore, but it can sometimes make for awkward double
negations (e.g., we can drop a few !!oidcmp() instances
here).
This patch was generated almost entirely by the included
coccinelle patch. This mechanical conversion should be
completely safe, because we check explicitly for cases where
oidcmp() is compared to 0, which is what oideq() is doing
under the hood. Note that we don't have to catch "!oidcmp()"
separately; coccinelle's standard isomorphisms make sure the
two are treated equivalently.
I say "almost" because I did hand-edit the coccinelle output
to fix up a few style violations (it mostly keeps the
original formatting, but sometimes unwraps long lines).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-29 00:22:40 +03:00
|
|
|
} else if (oideq(&ds->candidate, current)) {
|
2012-06-21 09:07:36 +04:00
|
|
|
/* the same as what we already have seen */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ds->fn) {
|
|
|
|
/* cannot disambiguate between ds->candidate and current */
|
|
|
|
ds->ambiguous = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ds->candidate_checked) {
|
2019-04-16 12:33:23 +03:00
|
|
|
ds->candidate_ok = ds->fn(ds->repo, &ds->candidate, ds->cb_data);
|
2012-06-21 09:07:36 +04:00
|
|
|
ds->disambiguate_fn_used = 1;
|
|
|
|
ds->candidate_checked = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ds->candidate_ok) {
|
2013-07-23 01:02:23 +04:00
|
|
|
/* discard the candidate; we know it does not satisfy fn */
|
2017-03-26 19:01:34 +03:00
|
|
|
oidcpy(&ds->candidate, current);
|
2012-06-21 09:07:36 +04:00
|
|
|
ds->candidate_checked = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if we reach this point, we know ds->candidate satisfies fn */
|
2019-04-16 12:33:23 +03:00
|
|
|
if (ds->fn(ds->repo, current, ds->cb_data)) {
|
2012-06-21 09:07:36 +04:00
|
|
|
/*
|
|
|
|
* if both current and candidate satisfy fn, we cannot
|
|
|
|
* disambiguate.
|
|
|
|
*/
|
|
|
|
ds->candidate_ok = 0;
|
|
|
|
ds->ambiguous = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* otherwise, current can be discarded and candidate is still good */
|
|
|
|
}
|
|
|
|
|
2020-12-31 14:56:20 +03:00
|
|
|
static int match_hash(unsigned, const unsigned char *, const unsigned char *);
|
2017-06-22 21:19:48 +03:00
|
|
|
|
2021-07-08 02:10:19 +03:00
|
|
|
static enum cb_next match_prefix(const struct object_id *oid, void *arg)
|
|
|
|
{
|
|
|
|
struct disambiguate_state *ds = arg;
|
|
|
|
/* no need to call match_hash, oidtree_each did prefix match */
|
|
|
|
update_candidates(ds, oid);
|
|
|
|
return ds->ambiguous ? CB_BREAK : CB_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2016-09-26 15:00:04 +03:00
|
|
|
static void find_short_object_filename(struct disambiguate_state *ds)
|
2005-08-04 09:15:49 +04:00
|
|
|
{
|
2018-11-12 17:48:47 +03:00
|
|
|
struct object_directory *odb;
|
2005-10-03 08:40:51 +04:00
|
|
|
|
2021-07-08 02:10:19 +03:00
|
|
|
for (odb = ds->repo->objects->odb; odb && !ds->ambiguous; odb = odb->next)
|
|
|
|
oidtree_each(odb_loose_cache(odb, &ds->bin_pfx),
|
|
|
|
&ds->bin_pfx, ds->len, match_prefix, ds);
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
|
|
|
|
2020-12-31 14:56:20 +03:00
|
|
|
static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
|
2005-08-04 09:15:49 +04:00
|
|
|
{
|
|
|
|
do {
|
|
|
|
if (*a != *b)
|
|
|
|
return 0;
|
|
|
|
a++;
|
|
|
|
b++;
|
|
|
|
len -= 2;
|
|
|
|
} while (len > 1);
|
|
|
|
if (len)
|
|
|
|
if ((*a ^ *b) & 0xf0)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-07-12 22:39:35 +03:00
|
|
|
static void unique_in_midx(struct multi_pack_index *m,
|
|
|
|
struct disambiguate_state *ds)
|
|
|
|
{
|
|
|
|
uint32_t num, i, first = 0;
|
|
|
|
const struct object_id *current = NULL;
|
|
|
|
num = m->num_objects;
|
|
|
|
|
|
|
|
if (!num)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bsearch_midx(&ds->bin_pfx, m, &first);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* At this point, "first" is the location of the lowest object
|
|
|
|
* with an object name that could match "bin_pfx". See if we have
|
|
|
|
* 0, 1 or more objects that actually match(es).
|
|
|
|
*/
|
|
|
|
for (i = first; i < num && !ds->ambiguous; i++) {
|
|
|
|
struct object_id oid;
|
|
|
|
current = nth_midxed_object_oid(&oid, m, i);
|
2020-12-31 14:56:20 +03:00
|
|
|
if (!match_hash(ds->len, ds->bin_pfx.hash, current->hash))
|
2018-07-12 22:39:35 +03:00
|
|
|
break;
|
|
|
|
update_candidates(ds, current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-26 15:00:04 +03:00
|
|
|
static void unique_in_pack(struct packed_git *p,
|
2012-06-21 09:07:36 +04:00
|
|
|
struct disambiguate_state *ds)
|
2005-08-04 09:15:49 +04:00
|
|
|
{
|
2018-03-24 19:41:08 +03:00
|
|
|
uint32_t num, i, first = 0;
|
2012-06-19 00:10:38 +04:00
|
|
|
|
midx: add packs to packed_git linked list
The multi-pack-index allows searching for objects across multiple
packs using one object list. The original design gains many of
these performance benefits by keeping the packs in the
multi-pack-index out of the packed_git list.
Unfortunately, this has one major drawback. If the multi-pack-index
covers thousands of packs, and a command loads many of those packs,
then we can hit the limit for open file descriptors. The
close_one_pack() method is used to limit this resource, but it
only looks at the packed_git list, and uses an LRU cache to prevent
thrashing.
Instead of complicating this close_one_pack() logic to include
direct references to the multi-pack-index, simply add the packs
opened by the multi-pack-index to the packed_git list. This
immediately solves the file-descriptor limit problem, but requires
some extra steps to avoid performance issues or other problems:
1. Create a multi_pack_index bit in the packed_git struct that is
one if and only if the pack was loaded from a multi-pack-index.
2. Skip packs with the multi_pack_index bit when doing object
lookups and abbreviations. These algorithms already check the
multi-pack-index before the packed_git struct. This has a very
small performance hit, as we need to walk more packed_git
structs. This is acceptable, since these operations run binary
search on the other packs, so this walk-and-ignore logic is
very fast by comparison.
3. When closing a multi-pack-index file, do not close its packs,
as those packs will be closed using close_all_packs(). In some
cases, such as 'git repack', we run 'close_midx()' without also
closing the packs, so we need to un-set the multi_pack_index bit
in those packs. This is necessary, and caught by running
t6501-freshen-objects.sh with GIT_TEST_MULTI_PACK_INDEX=1.
To manually test this change, I inserted trace2 logging into
close_pack_fd() and set pack_max_fds to 10, then ran 'git rev-list
--all --objects' on a copy of the Git repo with 300+ pack-files and
a multi-pack-index. The logs verified the packs are closed as
we read them beyond the file descriptor limit.
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-04-29 19:18:56 +03:00
|
|
|
if (p->multi_pack_index)
|
|
|
|
return;
|
|
|
|
|
2017-10-12 15:02:20 +03:00
|
|
|
if (open_pack_index(p) || !p->num_objects)
|
|
|
|
return;
|
|
|
|
|
2012-06-19 00:10:38 +04:00
|
|
|
num = p->num_objects;
|
2018-03-24 19:41:08 +03:00
|
|
|
bsearch_pack(&ds->bin_pfx, p, &first);
|
2012-06-19 00:10:38 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* At this point, "first" is the location of the lowest object
|
2012-06-21 09:35:43 +04:00
|
|
|
* with an object name that could match "bin_pfx". See if we have
|
2012-06-19 00:10:38 +04:00
|
|
|
* 0, 1 or more objects that actually match(es).
|
|
|
|
*/
|
2012-06-21 09:07:36 +04:00
|
|
|
for (i = first; i < num && !ds->ambiguous; i++) {
|
2017-03-26 19:01:34 +03:00
|
|
|
struct object_id oid;
|
2020-02-24 07:27:36 +03:00
|
|
|
nth_packed_object_id(&oid, p, i);
|
2020-12-31 14:56:20 +03:00
|
|
|
if (!match_hash(ds->len, ds->bin_pfx.hash, oid.hash))
|
2012-06-19 00:10:38 +04:00
|
|
|
break;
|
2020-02-24 07:27:36 +03:00
|
|
|
update_candidates(ds, &oid);
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
2012-06-19 00:10:38 +04:00
|
|
|
}
|
|
|
|
|
2016-09-26 15:00:04 +03:00
|
|
|
static void find_short_packed_object(struct disambiguate_state *ds)
|
2005-08-04 09:15:49 +04:00
|
|
|
{
|
2018-07-12 22:39:35 +03:00
|
|
|
struct multi_pack_index *m;
|
2005-08-04 09:15:49 +04:00
|
|
|
struct packed_git *p;
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous;
|
2018-07-12 22:39:35 +03:00
|
|
|
m = m->next)
|
|
|
|
unique_in_midx(m, ds);
|
2019-04-16 12:33:23 +03:00
|
|
|
for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
|
2018-03-23 20:20:59 +03:00
|
|
|
p = p->next)
|
2016-09-26 15:00:04 +03:00
|
|
|
unique_in_pack(p, ds);
|
2005-10-03 08:40:51 +04:00
|
|
|
}
|
|
|
|
|
2012-06-21 09:07:36 +04:00
|
|
|
static int finish_object_disambiguation(struct disambiguate_state *ds,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
struct object_id *oid)
|
2005-10-03 08:40:51 +04:00
|
|
|
{
|
2012-06-21 09:07:36 +04:00
|
|
|
if (ds->ambiguous)
|
|
|
|
return SHORT_NAME_AMBIGUOUS;
|
2005-10-03 08:40:51 +04:00
|
|
|
|
2012-06-21 09:07:36 +04:00
|
|
|
if (!ds->candidate_exists)
|
2019-01-18 07:19:43 +03:00
|
|
|
return MISSING_OBJECT;
|
2012-06-21 09:07:36 +04:00
|
|
|
|
|
|
|
if (!ds->candidate_checked)
|
|
|
|
/*
|
|
|
|
* If this is the only candidate, there is no point
|
|
|
|
* calling the disambiguation hint callback.
|
|
|
|
*
|
|
|
|
* On the other hand, if the current candidate
|
|
|
|
* replaced an earlier candidate that did _not_ pass
|
|
|
|
* the disambiguation hint callback, then we do have
|
|
|
|
* more than one objects that match the short name
|
|
|
|
* given, so we should make sure this one matches;
|
|
|
|
* otherwise, if we discovered this one and the one
|
|
|
|
* that we previously discarded in the reverse order,
|
|
|
|
* we would end up showing different results in the
|
|
|
|
* same repository!
|
|
|
|
*/
|
|
|
|
ds->candidate_ok = (!ds->disambiguate_fn_used ||
|
2019-04-16 12:33:23 +03:00
|
|
|
ds->fn(ds->repo, &ds->candidate, ds->cb_data));
|
2012-06-21 09:07:36 +04:00
|
|
|
|
|
|
|
if (!ds->candidate_ok)
|
2005-10-12 02:22:48 +04:00
|
|
|
return SHORT_NAME_AMBIGUOUS;
|
2012-06-21 09:07:36 +04:00
|
|
|
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oidcpy(oid, &ds->candidate);
|
2005-08-04 09:15:49 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
static int disambiguate_commit_only(struct repository *r,
|
|
|
|
const struct object_id *oid,
|
|
|
|
void *cb_data_unused)
|
2012-06-21 10:03:09 +04:00
|
|
|
{
|
2019-04-16 12:33:23 +03:00
|
|
|
int kind = oid_object_info(r, oid, NULL);
|
2012-06-21 10:03:09 +04:00
|
|
|
return kind == OBJ_COMMIT;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
static int disambiguate_committish_only(struct repository *r,
|
|
|
|
const struct object_id *oid,
|
|
|
|
void *cb_data_unused)
|
2012-07-02 21:00:40 +04:00
|
|
|
{
|
|
|
|
struct object *obj;
|
|
|
|
int kind;
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
kind = oid_object_info(r, oid, NULL);
|
2012-07-02 21:00:40 +04:00
|
|
|
if (kind == OBJ_COMMIT)
|
|
|
|
return 1;
|
|
|
|
if (kind != OBJ_TAG)
|
2005-10-03 08:40:51 +04:00
|
|
|
return 0;
|
2012-07-02 21:00:40 +04:00
|
|
|
|
|
|
|
/* We need to do this the hard way... */
|
2019-04-16 12:33:23 +03:00
|
|
|
obj = deref_tag(r, parse_object(r, oid), NULL, 0);
|
2012-07-02 21:00:40 +04:00
|
|
|
if (obj && obj->type == OBJ_COMMIT)
|
|
|
|
return 1;
|
2005-08-04 09:15:49 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
static int disambiguate_tree_only(struct repository *r,
|
|
|
|
const struct object_id *oid,
|
|
|
|
void *cb_data_unused)
|
2005-08-04 09:15:49 +04:00
|
|
|
{
|
2019-04-16 12:33:23 +03:00
|
|
|
int kind = oid_object_info(r, oid, NULL);
|
2012-07-03 10:35:05 +04:00
|
|
|
return kind == OBJ_TREE;
|
|
|
|
}
|
2005-08-04 09:15:49 +04:00
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
static int disambiguate_treeish_only(struct repository *r,
|
|
|
|
const struct object_id *oid,
|
|
|
|
void *cb_data_unused)
|
2012-07-03 10:35:05 +04:00
|
|
|
{
|
|
|
|
struct object *obj;
|
|
|
|
int kind;
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
kind = oid_object_info(r, oid, NULL);
|
2012-07-03 10:35:05 +04:00
|
|
|
if (kind == OBJ_TREE || kind == OBJ_COMMIT)
|
|
|
|
return 1;
|
|
|
|
if (kind != OBJ_TAG)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* We need to do this the hard way... */
|
2019-04-16 12:33:23 +03:00
|
|
|
obj = deref_tag(r, parse_object(r, oid), NULL, 0);
|
2012-07-03 10:35:05 +04:00
|
|
|
if (obj && (obj->type == OBJ_TREE || obj->type == OBJ_COMMIT))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
static int disambiguate_blob_only(struct repository *r,
|
|
|
|
const struct object_id *oid,
|
|
|
|
void *cb_data_unused)
|
2012-07-03 10:35:05 +04:00
|
|
|
{
|
2019-04-16 12:33:23 +03:00
|
|
|
int kind = oid_object_info(r, oid, NULL);
|
2012-07-03 10:35:05 +04:00
|
|
|
return kind == OBJ_BLOB;
|
|
|
|
}
|
|
|
|
|
2016-09-27 15:38:01 +03:00
|
|
|
static disambiguate_hint_fn default_disambiguate_hint;
|
|
|
|
|
|
|
|
int set_disambiguate_hint_config(const char *var, const char *value)
|
|
|
|
{
|
|
|
|
static const struct {
|
|
|
|
const char *name;
|
|
|
|
disambiguate_hint_fn fn;
|
|
|
|
} hints[] = {
|
|
|
|
{ "none", NULL },
|
|
|
|
{ "commit", disambiguate_commit_only },
|
|
|
|
{ "committish", disambiguate_committish_only },
|
|
|
|
{ "tree", disambiguate_tree_only },
|
|
|
|
{ "treeish", disambiguate_treeish_only },
|
|
|
|
{ "blob", disambiguate_blob_only }
|
|
|
|
};
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!value)
|
|
|
|
return config_error_nonbool(var);
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(hints); i++) {
|
|
|
|
if (!strcasecmp(value, hints[i].name)) {
|
|
|
|
default_disambiguate_hint = hints[i].fn;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return error("unknown hint type for '%s': %s", var, value);
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
static int init_object_disambiguation(struct repository *r,
|
|
|
|
const char *name, int len,
|
2016-09-26 15:00:04 +03:00
|
|
|
struct disambiguate_state *ds)
|
2005-08-04 09:15:49 +04:00
|
|
|
{
|
2012-07-04 01:21:59 +04:00
|
|
|
int i;
|
2005-08-04 09:15:49 +04:00
|
|
|
|
2018-07-16 04:27:58 +03:00
|
|
|
if (len < MINIMUM_ABBREV || len > the_hash_algo->hexsz)
|
2016-09-26 15:00:04 +03:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
memset(ds, 0, sizeof(*ds));
|
|
|
|
|
2005-09-20 02:16:03 +04:00
|
|
|
for (i = 0; i < len ;i++) {
|
2005-08-04 09:15:49 +04:00
|
|
|
unsigned char c = name[i];
|
|
|
|
unsigned char val;
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
val = c - '0';
|
|
|
|
else if (c >= 'a' && c <= 'f')
|
|
|
|
val = c - 'a' + 10;
|
|
|
|
else if (c >= 'A' && c <='F') {
|
|
|
|
val = c - 'A' + 10;
|
|
|
|
c -= 'A' - 'a';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return -1;
|
2016-09-26 15:00:04 +03:00
|
|
|
ds->hex_pfx[i] = c;
|
2005-08-04 09:15:49 +04:00
|
|
|
if (!(i & 1))
|
|
|
|
val <<= 4;
|
2017-03-26 19:01:33 +03:00
|
|
|
ds->bin_pfx.hash[i >> 1] |= val;
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
2016-09-26 15:00:04 +03:00
|
|
|
|
|
|
|
ds->len = len;
|
2016-09-26 15:00:07 +03:00
|
|
|
ds->hex_pfx[len] = '\0';
|
2019-04-16 12:33:23 +03:00
|
|
|
ds->repo = r;
|
|
|
|
prepare_alt_odb(r);
|
2012-07-04 01:21:59 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-31 04:39:59 +03:00
|
|
|
static int show_ambiguous_object(const struct object_id *oid, void *data)
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
{
|
|
|
|
const struct disambiguate_state *ds = data;
|
|
|
|
struct strbuf desc = STRBUF_INIT;
|
|
|
|
int type;
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
if (ds->fn && !ds->fn(ds->repo, oid, ds->cb_data))
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
return 0;
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
type = oid_object_info(ds->repo, oid, NULL);
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
if (type == OBJ_COMMIT) {
|
2019-04-16 12:33:23 +03:00
|
|
|
struct commit *commit = lookup_commit(ds->repo, oid);
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
if (commit) {
|
|
|
|
struct pretty_print_context pp = {0};
|
|
|
|
pp.date_mode.type = DATE_SHORT;
|
|
|
|
format_commit_message(commit, " %ad - %s", &desc, &pp);
|
|
|
|
}
|
|
|
|
} else if (type == OBJ_TAG) {
|
2019-04-16 12:33:23 +03:00
|
|
|
struct tag *tag = lookup_tag(ds->repo, oid);
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
if (!parse_tag(tag) && tag->tag)
|
|
|
|
strbuf_addf(&desc, " %s", tag->tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
advise(" %s %s%s",
|
2019-04-16 12:33:23 +03:00
|
|
|
repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV),
|
2018-02-14 21:59:24 +03:00
|
|
|
type_name(type) ? type_name(type) : "unknown type",
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
desc.buf);
|
|
|
|
|
|
|
|
strbuf_release(&desc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-10 15:43:01 +03:00
|
|
|
static int collect_ambiguous(const struct object_id *oid, void *data)
|
|
|
|
{
|
|
|
|
oid_array_append(data, oid);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
static int repo_collect_ambiguous(struct repository *r,
|
|
|
|
const struct object_id *oid,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
return collect_ambiguous(oid, data);
|
|
|
|
}
|
|
|
|
|
2019-08-20 21:49:12 +03:00
|
|
|
static int sort_ambiguous(const void *a, const void *b, void *ctx)
|
get_short_oid: sort ambiguous objects by type, then SHA-1
Change the output emitted when an ambiguous object is encountered so
that we show tags first, then commits, followed by trees, and finally
blobs. Within each type we show objects in hashcmp() order. Before
this change the objects were only ordered by hashcmp().
The reason for doing this is that the output looks better as a result,
e.g. the v2.17.0 tag before this change on "git show e8f2" would
display:
hint: The candidates are:
hint: e8f2093055 tree
hint: e8f21caf94 commit 2013-06-24 - bash prompt: print unique detached HEAD abbreviated object name
hint: e8f21d02f7 blob
hint: e8f21d577c blob
hint: e8f25a3a50 tree
hint: e8f26250fa commit 2017-02-03 - Merge pull request #996 from jeffhostetler/jeffhostetler/register_rename_src
hint: e8f2650052 tag v2.17.0
hint: e8f2867228 blob
hint: e8f28d537c tree
hint: e8f2a35526 blob
hint: e8f2bc0c06 commit 2015-05-10 - Documentation: note behavior for multiple remote.url entries
hint: e8f2cf6ec0 tree
Now we'll instead show:
hint: e8f2650052 tag v2.17.0
hint: e8f21caf94 commit 2013-06-24 - bash prompt: print unique detached HEAD abbreviated object name
hint: e8f26250fa commit 2017-02-03 - Merge pull request #996 from jeffhostetler/jeffhostetler/register_rename_src
hint: e8f2bc0c06 commit 2015-05-10 - Documentation: note behavior for multiple remote.url entries
hint: e8f2093055 tree
hint: e8f25a3a50 tree
hint: e8f28d537c tree
hint: e8f2cf6ec0 tree
hint: e8f21d02f7 blob
hint: e8f21d577c blob
hint: e8f2867228 blob
hint: e8f2a35526 blob
Since we show the commit data in the output that's nicely aligned once
we sort by object type. The decision to show tags before commits is
pretty arbitrary. I don't want to order by object_type since there
tags come last after blobs, which doesn't make sense if we want to
show the most important things first.
I could display them after commits, but it's much less likely that
we'll display a tag, so if there is one it makes sense to show it
prominently at the top.
A note on the implementation: Derrick rightly pointed out[1] that
we're bending over backwards here in get_short_oid() to first
de-duplicate the list, and then emit it, but could simply do it in one
step.
The reason for that is that oid_array_for_each_unique() doesn't
actually require that the array be sorted by oid_array_sort(), it just
needs to be sorted in some order that guarantees that all objects with
the same ID are adjacent to one another, which (barring a hash
collision, which'll be someone else's problem) the sort_ambiguous()
function does.
I agree that would be simpler for this code, and had forgotten why I
initially wrote it like this[2]. But on further reflection I think
it's better to do more work here just so we're not underhandedly using
the oid-array API where we lie about the list being sorted. That would
break any subsequent use of oid_array_lookup() in subtle ways.
I could get around that by hacking the API itself to support this
use-case and documenting it, which I did as a WIP patch in [3], but I
think it's too much code smell just for this one call site. It's
simpler for the API to just introduce a oid_array_for_each() function
to eagerly spew out the list without sorting or de-duplication, and
then do the de-duplication and sorting in two passes.
1. https://public-inbox.org/git/20180501130318.58251-1-dstolee@microsoft.com/
2. https://public-inbox.org/git/876047ze9v.fsf@evledraar.gmail.com/
3. https://public-inbox.org/git/874ljrzctc.fsf@evledraar.gmail.com/
Helped-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-10 15:43:02 +03:00
|
|
|
{
|
2019-08-20 21:49:12 +03:00
|
|
|
struct repository *sort_ambiguous_repo = ctx;
|
2019-04-16 12:33:20 +03:00
|
|
|
int a_type = oid_object_info(sort_ambiguous_repo, a, NULL);
|
|
|
|
int b_type = oid_object_info(sort_ambiguous_repo, b, NULL);
|
get_short_oid: sort ambiguous objects by type, then SHA-1
Change the output emitted when an ambiguous object is encountered so
that we show tags first, then commits, followed by trees, and finally
blobs. Within each type we show objects in hashcmp() order. Before
this change the objects were only ordered by hashcmp().
The reason for doing this is that the output looks better as a result,
e.g. the v2.17.0 tag before this change on "git show e8f2" would
display:
hint: The candidates are:
hint: e8f2093055 tree
hint: e8f21caf94 commit 2013-06-24 - bash prompt: print unique detached HEAD abbreviated object name
hint: e8f21d02f7 blob
hint: e8f21d577c blob
hint: e8f25a3a50 tree
hint: e8f26250fa commit 2017-02-03 - Merge pull request #996 from jeffhostetler/jeffhostetler/register_rename_src
hint: e8f2650052 tag v2.17.0
hint: e8f2867228 blob
hint: e8f28d537c tree
hint: e8f2a35526 blob
hint: e8f2bc0c06 commit 2015-05-10 - Documentation: note behavior for multiple remote.url entries
hint: e8f2cf6ec0 tree
Now we'll instead show:
hint: e8f2650052 tag v2.17.0
hint: e8f21caf94 commit 2013-06-24 - bash prompt: print unique detached HEAD abbreviated object name
hint: e8f26250fa commit 2017-02-03 - Merge pull request #996 from jeffhostetler/jeffhostetler/register_rename_src
hint: e8f2bc0c06 commit 2015-05-10 - Documentation: note behavior for multiple remote.url entries
hint: e8f2093055 tree
hint: e8f25a3a50 tree
hint: e8f28d537c tree
hint: e8f2cf6ec0 tree
hint: e8f21d02f7 blob
hint: e8f21d577c blob
hint: e8f2867228 blob
hint: e8f2a35526 blob
Since we show the commit data in the output that's nicely aligned once
we sort by object type. The decision to show tags before commits is
pretty arbitrary. I don't want to order by object_type since there
tags come last after blobs, which doesn't make sense if we want to
show the most important things first.
I could display them after commits, but it's much less likely that
we'll display a tag, so if there is one it makes sense to show it
prominently at the top.
A note on the implementation: Derrick rightly pointed out[1] that
we're bending over backwards here in get_short_oid() to first
de-duplicate the list, and then emit it, but could simply do it in one
step.
The reason for that is that oid_array_for_each_unique() doesn't
actually require that the array be sorted by oid_array_sort(), it just
needs to be sorted in some order that guarantees that all objects with
the same ID are adjacent to one another, which (barring a hash
collision, which'll be someone else's problem) the sort_ambiguous()
function does.
I agree that would be simpler for this code, and had forgotten why I
initially wrote it like this[2]. But on further reflection I think
it's better to do more work here just so we're not underhandedly using
the oid-array API where we lie about the list being sorted. That would
break any subsequent use of oid_array_lookup() in subtle ways.
I could get around that by hacking the API itself to support this
use-case and documenting it, which I did as a WIP patch in [3], but I
think it's too much code smell just for this one call site. It's
simpler for the API to just introduce a oid_array_for_each() function
to eagerly spew out the list without sorting or de-duplication, and
then do the de-duplication and sorting in two passes.
1. https://public-inbox.org/git/20180501130318.58251-1-dstolee@microsoft.com/
2. https://public-inbox.org/git/876047ze9v.fsf@evledraar.gmail.com/
3. https://public-inbox.org/git/874ljrzctc.fsf@evledraar.gmail.com/
Helped-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-10 15:43:02 +03:00
|
|
|
int a_type_sort;
|
|
|
|
int b_type_sort;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sorts by hash within the same object type, just as
|
|
|
|
* oid_array_for_each_unique() would do.
|
|
|
|
*/
|
|
|
|
if (a_type == b_type)
|
|
|
|
return oidcmp(a, b);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Between object types show tags, then commits, and finally
|
|
|
|
* trees and blobs.
|
|
|
|
*
|
|
|
|
* The object_type enum is commit, tree, blob, tag, but we
|
|
|
|
* want tag, commit, tree blob. Cleverly (perhaps too
|
|
|
|
* cleverly) do that with modulus, since the enum assigns 1 to
|
|
|
|
* commit, so tag becomes 0.
|
|
|
|
*/
|
|
|
|
a_type_sort = a_type % 4;
|
|
|
|
b_type_sort = b_type % 4;
|
|
|
|
return a_type_sort > b_type_sort ? 1 : -1;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:20 +03:00
|
|
|
static void sort_ambiguous_oid_array(struct repository *r, struct oid_array *a)
|
|
|
|
{
|
2019-08-20 21:49:12 +03:00
|
|
|
QSORT_S(a->oid, a->nr, sort_ambiguous, r);
|
2019-04-16 12:33:20 +03:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:25 +03:00
|
|
|
static enum get_oid_result get_short_oid(struct repository *r,
|
|
|
|
const char *name, int len,
|
2019-01-18 07:19:43 +03:00
|
|
|
struct object_id *oid,
|
|
|
|
unsigned flags)
|
2012-07-04 01:21:59 +04:00
|
|
|
{
|
|
|
|
int status;
|
|
|
|
struct disambiguate_state ds;
|
2017-07-14 02:49:29 +03:00
|
|
|
int quietly = !!(flags & GET_OID_QUIETLY);
|
2012-07-04 01:21:59 +04:00
|
|
|
|
2019-04-16 12:33:25 +03:00
|
|
|
if (init_object_disambiguation(r, name, len, &ds) < 0)
|
2012-07-04 01:21:59 +04:00
|
|
|
return -1;
|
2005-10-03 08:40:51 +04:00
|
|
|
|
2017-07-14 02:49:29 +03:00
|
|
|
if (HAS_MULTI_BITS(flags & GET_OID_DISAMBIGUATORS))
|
2018-05-02 12:38:39 +03:00
|
|
|
BUG("multiple get_short_oid disambiguator flags");
|
2016-09-26 14:59:01 +03:00
|
|
|
|
2017-07-14 02:49:29 +03:00
|
|
|
if (flags & GET_OID_COMMIT)
|
2012-06-21 10:03:09 +04:00
|
|
|
ds.fn = disambiguate_commit_only;
|
2017-07-14 02:49:29 +03:00
|
|
|
else if (flags & GET_OID_COMMITTISH)
|
2012-07-02 21:00:40 +04:00
|
|
|
ds.fn = disambiguate_committish_only;
|
2017-07-14 02:49:29 +03:00
|
|
|
else if (flags & GET_OID_TREE)
|
2012-07-03 10:35:05 +04:00
|
|
|
ds.fn = disambiguate_tree_only;
|
2017-07-14 02:49:29 +03:00
|
|
|
else if (flags & GET_OID_TREEISH)
|
2012-07-03 10:35:05 +04:00
|
|
|
ds.fn = disambiguate_treeish_only;
|
2017-07-14 02:49:29 +03:00
|
|
|
else if (flags & GET_OID_BLOB)
|
2012-07-03 10:35:05 +04:00
|
|
|
ds.fn = disambiguate_blob_only;
|
2016-09-27 15:38:01 +03:00
|
|
|
else
|
|
|
|
ds.fn = default_disambiguate_hint;
|
2012-06-21 10:03:09 +04:00
|
|
|
|
2016-09-26 15:00:04 +03:00
|
|
|
find_short_object_filename(&ds);
|
|
|
|
find_short_packed_object(&ds);
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
status = finish_object_disambiguation(&ds, oid);
|
2005-10-03 08:40:51 +04:00
|
|
|
|
2019-03-13 13:16:34 +03:00
|
|
|
/*
|
|
|
|
* If we didn't find it, do the usual reprepare() slow-path,
|
|
|
|
* since the object may have recently been added to the repository
|
|
|
|
* or migrated from loose to packed.
|
|
|
|
*/
|
|
|
|
if (status == MISSING_OBJECT) {
|
2019-06-27 12:28:52 +03:00
|
|
|
reprepare_packed_git(r);
|
2019-03-13 13:16:34 +03:00
|
|
|
find_short_object_filename(&ds);
|
|
|
|
find_short_packed_object(&ds);
|
|
|
|
status = finish_object_disambiguation(&ds, oid);
|
|
|
|
}
|
|
|
|
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) {
|
get_short_oid: sort ambiguous objects by type, then SHA-1
Change the output emitted when an ambiguous object is encountered so
that we show tags first, then commits, followed by trees, and finally
blobs. Within each type we show objects in hashcmp() order. Before
this change the objects were only ordered by hashcmp().
The reason for doing this is that the output looks better as a result,
e.g. the v2.17.0 tag before this change on "git show e8f2" would
display:
hint: The candidates are:
hint: e8f2093055 tree
hint: e8f21caf94 commit 2013-06-24 - bash prompt: print unique detached HEAD abbreviated object name
hint: e8f21d02f7 blob
hint: e8f21d577c blob
hint: e8f25a3a50 tree
hint: e8f26250fa commit 2017-02-03 - Merge pull request #996 from jeffhostetler/jeffhostetler/register_rename_src
hint: e8f2650052 tag v2.17.0
hint: e8f2867228 blob
hint: e8f28d537c tree
hint: e8f2a35526 blob
hint: e8f2bc0c06 commit 2015-05-10 - Documentation: note behavior for multiple remote.url entries
hint: e8f2cf6ec0 tree
Now we'll instead show:
hint: e8f2650052 tag v2.17.0
hint: e8f21caf94 commit 2013-06-24 - bash prompt: print unique detached HEAD abbreviated object name
hint: e8f26250fa commit 2017-02-03 - Merge pull request #996 from jeffhostetler/jeffhostetler/register_rename_src
hint: e8f2bc0c06 commit 2015-05-10 - Documentation: note behavior for multiple remote.url entries
hint: e8f2093055 tree
hint: e8f25a3a50 tree
hint: e8f28d537c tree
hint: e8f2cf6ec0 tree
hint: e8f21d02f7 blob
hint: e8f21d577c blob
hint: e8f2867228 blob
hint: e8f2a35526 blob
Since we show the commit data in the output that's nicely aligned once
we sort by object type. The decision to show tags before commits is
pretty arbitrary. I don't want to order by object_type since there
tags come last after blobs, which doesn't make sense if we want to
show the most important things first.
I could display them after commits, but it's much less likely that
we'll display a tag, so if there is one it makes sense to show it
prominently at the top.
A note on the implementation: Derrick rightly pointed out[1] that
we're bending over backwards here in get_short_oid() to first
de-duplicate the list, and then emit it, but could simply do it in one
step.
The reason for that is that oid_array_for_each_unique() doesn't
actually require that the array be sorted by oid_array_sort(), it just
needs to be sorted in some order that guarantees that all objects with
the same ID are adjacent to one another, which (barring a hash
collision, which'll be someone else's problem) the sort_ambiguous()
function does.
I agree that would be simpler for this code, and had forgotten why I
initially wrote it like this[2]. But on further reflection I think
it's better to do more work here just so we're not underhandedly using
the oid-array API where we lie about the list being sorted. That would
break any subsequent use of oid_array_lookup() in subtle ways.
I could get around that by hacking the API itself to support this
use-case and documenting it, which I did as a WIP patch in [3], but I
think it's too much code smell just for this one call site. It's
simpler for the API to just introduce a oid_array_for_each() function
to eagerly spew out the list without sorting or de-duplication, and
then do the de-duplication and sorting in two passes.
1. https://public-inbox.org/git/20180501130318.58251-1-dstolee@microsoft.com/
2. https://public-inbox.org/git/876047ze9v.fsf@evledraar.gmail.com/
3. https://public-inbox.org/git/874ljrzctc.fsf@evledraar.gmail.com/
Helped-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-10 15:43:02 +03:00
|
|
|
struct oid_array collect = OID_ARRAY_INIT;
|
|
|
|
|
2020-12-31 14:56:20 +03:00
|
|
|
error(_("short object ID %s is ambiguous"), ds.hex_pfx);
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We may still have ambiguity if we simply saw a series of
|
|
|
|
* candidates that did not satisfy our hint function. In
|
|
|
|
* that case, we still want to show them, so disable the hint
|
|
|
|
* function entirely.
|
|
|
|
*/
|
|
|
|
if (!ds.ambiguous)
|
|
|
|
ds.fn = NULL;
|
|
|
|
|
|
|
|
advise(_("The candidates are:"));
|
2019-04-16 12:33:25 +03:00
|
|
|
repo_for_each_abbrev(r, ds.hex_pfx, collect_ambiguous, &collect);
|
|
|
|
sort_ambiguous_oid_array(r, &collect);
|
get_short_oid: sort ambiguous objects by type, then SHA-1
Change the output emitted when an ambiguous object is encountered so
that we show tags first, then commits, followed by trees, and finally
blobs. Within each type we show objects in hashcmp() order. Before
this change the objects were only ordered by hashcmp().
The reason for doing this is that the output looks better as a result,
e.g. the v2.17.0 tag before this change on "git show e8f2" would
display:
hint: The candidates are:
hint: e8f2093055 tree
hint: e8f21caf94 commit 2013-06-24 - bash prompt: print unique detached HEAD abbreviated object name
hint: e8f21d02f7 blob
hint: e8f21d577c blob
hint: e8f25a3a50 tree
hint: e8f26250fa commit 2017-02-03 - Merge pull request #996 from jeffhostetler/jeffhostetler/register_rename_src
hint: e8f2650052 tag v2.17.0
hint: e8f2867228 blob
hint: e8f28d537c tree
hint: e8f2a35526 blob
hint: e8f2bc0c06 commit 2015-05-10 - Documentation: note behavior for multiple remote.url entries
hint: e8f2cf6ec0 tree
Now we'll instead show:
hint: e8f2650052 tag v2.17.0
hint: e8f21caf94 commit 2013-06-24 - bash prompt: print unique detached HEAD abbreviated object name
hint: e8f26250fa commit 2017-02-03 - Merge pull request #996 from jeffhostetler/jeffhostetler/register_rename_src
hint: e8f2bc0c06 commit 2015-05-10 - Documentation: note behavior for multiple remote.url entries
hint: e8f2093055 tree
hint: e8f25a3a50 tree
hint: e8f28d537c tree
hint: e8f2cf6ec0 tree
hint: e8f21d02f7 blob
hint: e8f21d577c blob
hint: e8f2867228 blob
hint: e8f2a35526 blob
Since we show the commit data in the output that's nicely aligned once
we sort by object type. The decision to show tags before commits is
pretty arbitrary. I don't want to order by object_type since there
tags come last after blobs, which doesn't make sense if we want to
show the most important things first.
I could display them after commits, but it's much less likely that
we'll display a tag, so if there is one it makes sense to show it
prominently at the top.
A note on the implementation: Derrick rightly pointed out[1] that
we're bending over backwards here in get_short_oid() to first
de-duplicate the list, and then emit it, but could simply do it in one
step.
The reason for that is that oid_array_for_each_unique() doesn't
actually require that the array be sorted by oid_array_sort(), it just
needs to be sorted in some order that guarantees that all objects with
the same ID are adjacent to one another, which (barring a hash
collision, which'll be someone else's problem) the sort_ambiguous()
function does.
I agree that would be simpler for this code, and had forgotten why I
initially wrote it like this[2]. But on further reflection I think
it's better to do more work here just so we're not underhandedly using
the oid-array API where we lie about the list being sorted. That would
break any subsequent use of oid_array_lookup() in subtle ways.
I could get around that by hacking the API itself to support this
use-case and documenting it, which I did as a WIP patch in [3], but I
think it's too much code smell just for this one call site. It's
simpler for the API to just introduce a oid_array_for_each() function
to eagerly spew out the list without sorting or de-duplication, and
then do the de-duplication and sorting in two passes.
1. https://public-inbox.org/git/20180501130318.58251-1-dstolee@microsoft.com/
2. https://public-inbox.org/git/876047ze9v.fsf@evledraar.gmail.com/
3. https://public-inbox.org/git/874ljrzctc.fsf@evledraar.gmail.com/
Helped-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-10 15:43:02 +03:00
|
|
|
|
|
|
|
if (oid_array_for_each(&collect, show_ambiguous_object, &ds))
|
|
|
|
BUG("show_ambiguous_object shouldn't return non-zero");
|
|
|
|
oid_array_clear(&collect);
|
get_short_sha1: list ambiguous objects on error
When the user gives us an ambiguous short sha1, we print an
error and refuse to resolve it. In some cases, the next step
is for them to feed us more characters (e.g., if they were
retyping or cut-and-pasting from a full sha1). But in other
cases, that might be all they have. For example, an old
commit message may have used a 7-character hex that was
unique at the time, but is now ambiguous. Git doesn't
provide any information about the ambiguous objects it
found, so it's hard for the user to find out which one they
probably meant.
This patch teaches get_short_sha1() to list the sha1s of the
objects it found, along with a few bits of information that
may help the user decide which one they meant. Here's what
it looks like on git.git:
$ git rev-parse b2e1
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
hint: b2e1759 blob
hint: b2e18954 blob
hint: b2e1895c blob
fatal: ambiguous argument 'b2e1': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
We show the tagname for tags, and the date and subject for
commits. For trees and blobs, in theory we could dig in the
history to find the paths at which they were present. But
that's very expensive (on the order of 30s for the kernel),
and it's not likely to be all that helpful. Most short
references are to commits, so the useful information is
typically going to be that the object in question _isn't_ a
commit. So it's silly to spend a lot of CPU preemptively
digging up the path; the user can do it themselves if they
really need to.
And of course it's somewhat ironic that we abbreviate the
sha1s in the disambiguation hint. But full sha1s would cause
annoying line wrapping for the commit lines, and presumably
the user is going to just re-issue their command immediately
with the corrected sha1.
We also restrict the list to those that match any
disambiguation hint. E.g.:
$ git rev-parse b2e1:foo
error: short SHA1 b2e1 is ambiguous
hint: The candidates are:
hint: b2e1196 tag v2.8.0-rc1
hint: b2e11d1 tree
hint: b2e1632 commit 2007-11-14 - Merge branch 'bs/maint-commit-options'
fatal: Invalid object name 'b2e1'.
does not bother reporting the blobs, because they cannot
work as a treeish.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-26 15:00:36 +03:00
|
|
|
}
|
|
|
|
|
2005-10-12 02:22:48 +04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:24 +03:00
|
|
|
int repo_for_each_abbrev(struct repository *r, const char *prefix,
|
|
|
|
each_abbrev_fn fn, void *cb_data)
|
2012-07-04 01:21:59 +04:00
|
|
|
{
|
2017-03-31 04:40:00 +03:00
|
|
|
struct oid_array collect = OID_ARRAY_INIT;
|
2012-07-04 01:21:59 +04:00
|
|
|
struct disambiguate_state ds;
|
2016-09-26 15:00:33 +03:00
|
|
|
int ret;
|
2012-07-04 01:21:59 +04:00
|
|
|
|
2019-04-16 12:33:24 +03:00
|
|
|
if (init_object_disambiguation(r, prefix, strlen(prefix), &ds) < 0)
|
2012-07-04 01:21:59 +04:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
ds.always_call_fn = 1;
|
2019-04-16 12:33:23 +03:00
|
|
|
ds.fn = repo_collect_ambiguous;
|
2016-09-26 15:00:33 +03:00
|
|
|
ds.cb_data = &collect;
|
2016-09-26 15:00:04 +03:00
|
|
|
find_short_object_filename(&ds);
|
|
|
|
find_short_packed_object(&ds);
|
2016-09-26 15:00:33 +03:00
|
|
|
|
2017-03-31 04:40:00 +03:00
|
|
|
ret = oid_array_for_each_unique(&collect, fn, cb_data);
|
|
|
|
oid_array_clear(&collect);
|
2016-09-26 15:00:33 +03:00
|
|
|
return ret;
|
2012-07-04 01:21:59 +04:00
|
|
|
}
|
|
|
|
|
2016-10-04 02:47:28 +03:00
|
|
|
/*
|
|
|
|
* Return the slot of the most-significant bit set in "val". There are various
|
|
|
|
* ways to do this quickly with fls() or __builtin_clzl(), but speed is
|
|
|
|
* probably not a big deal here.
|
|
|
|
*/
|
|
|
|
static unsigned msb(unsigned long val)
|
|
|
|
{
|
|
|
|
unsigned r = 0;
|
|
|
|
while (val >>= 1)
|
|
|
|
r++;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2017-10-08 21:49:40 +03:00
|
|
|
struct min_abbrev_data {
|
|
|
|
unsigned int init_len;
|
|
|
|
unsigned int cur_len;
|
|
|
|
char *hex;
|
2019-04-16 12:33:21 +03:00
|
|
|
struct repository *repo;
|
2018-03-22 20:40:08 +03:00
|
|
|
const struct object_id *oid;
|
2017-10-08 21:49:40 +03:00
|
|
|
};
|
|
|
|
|
2017-10-12 15:02:19 +03:00
|
|
|
static inline char get_hex_char_from_oid(const struct object_id *oid,
|
|
|
|
unsigned int pos)
|
|
|
|
{
|
|
|
|
static const char hex[] = "0123456789abcdef";
|
|
|
|
|
|
|
|
if ((pos & 1) == 0)
|
|
|
|
return hex[oid->hash[pos >> 1] >> 4];
|
|
|
|
else
|
|
|
|
return hex[oid->hash[pos >> 1] & 0xf];
|
|
|
|
}
|
|
|
|
|
2017-10-08 21:49:40 +03:00
|
|
|
static int extend_abbrev_len(const struct object_id *oid, void *cb_data)
|
2005-10-12 02:22:48 +04:00
|
|
|
{
|
2017-10-08 21:49:40 +03:00
|
|
|
struct min_abbrev_data *mad = cb_data;
|
2005-12-14 04:21:41 +03:00
|
|
|
|
2017-10-08 21:49:40 +03:00
|
|
|
unsigned int i = mad->init_len;
|
2017-10-12 15:02:19 +03:00
|
|
|
while (mad->hex[i] && mad->hex[i] == get_hex_char_from_oid(oid, i))
|
2017-10-08 21:49:40 +03:00
|
|
|
i++;
|
|
|
|
|
|
|
|
if (i < GIT_MAX_RAWSZ && i >= mad->cur_len)
|
|
|
|
mad->cur_len = i + 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
static int repo_extend_abbrev_len(struct repository *r,
|
|
|
|
const struct object_id *oid,
|
|
|
|
void *cb_data)
|
|
|
|
{
|
|
|
|
return extend_abbrev_len(oid, cb_data);
|
|
|
|
}
|
|
|
|
|
2018-07-12 22:39:35 +03:00
|
|
|
static void find_abbrev_len_for_midx(struct multi_pack_index *m,
|
|
|
|
struct min_abbrev_data *mad)
|
|
|
|
{
|
|
|
|
int match = 0;
|
|
|
|
uint32_t num, first = 0;
|
|
|
|
struct object_id oid;
|
|
|
|
const struct object_id *mad_oid;
|
|
|
|
|
|
|
|
if (!m->num_objects)
|
|
|
|
return;
|
|
|
|
|
|
|
|
num = m->num_objects;
|
|
|
|
mad_oid = mad->oid;
|
|
|
|
match = bsearch_midx(mad_oid, m, &first);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* first is now the position in the packfile where we would insert
|
|
|
|
* mad->hash if it does not exist (or the position of mad->hash if
|
|
|
|
* it does exist). Hence, we consider a maximum of two objects
|
|
|
|
* nearby for the abbreviation length.
|
|
|
|
*/
|
|
|
|
mad->init_len = 0;
|
|
|
|
if (!match) {
|
|
|
|
if (nth_midxed_object_oid(&oid, m, first))
|
|
|
|
extend_abbrev_len(&oid, mad);
|
|
|
|
} else if (first < num - 1) {
|
|
|
|
if (nth_midxed_object_oid(&oid, m, first + 1))
|
|
|
|
extend_abbrev_len(&oid, mad);
|
|
|
|
}
|
|
|
|
if (first > 0) {
|
|
|
|
if (nth_midxed_object_oid(&oid, m, first - 1))
|
|
|
|
extend_abbrev_len(&oid, mad);
|
|
|
|
}
|
|
|
|
mad->init_len = mad->cur_len;
|
|
|
|
}
|
|
|
|
|
2017-10-12 15:02:20 +03:00
|
|
|
static void find_abbrev_len_for_pack(struct packed_git *p,
|
|
|
|
struct min_abbrev_data *mad)
|
2005-10-12 02:22:48 +04:00
|
|
|
{
|
2017-10-12 15:02:20 +03:00
|
|
|
int match = 0;
|
2018-03-22 20:40:10 +03:00
|
|
|
uint32_t num, first = 0;
|
2017-10-12 15:02:20 +03:00
|
|
|
struct object_id oid;
|
2018-03-22 20:40:10 +03:00
|
|
|
const struct object_id *mad_oid;
|
2017-10-12 15:02:20 +03:00
|
|
|
|
midx: add packs to packed_git linked list
The multi-pack-index allows searching for objects across multiple
packs using one object list. The original design gains many of
these performance benefits by keeping the packs in the
multi-pack-index out of the packed_git list.
Unfortunately, this has one major drawback. If the multi-pack-index
covers thousands of packs, and a command loads many of those packs,
then we can hit the limit for open file descriptors. The
close_one_pack() method is used to limit this resource, but it
only looks at the packed_git list, and uses an LRU cache to prevent
thrashing.
Instead of complicating this close_one_pack() logic to include
direct references to the multi-pack-index, simply add the packs
opened by the multi-pack-index to the packed_git list. This
immediately solves the file-descriptor limit problem, but requires
some extra steps to avoid performance issues or other problems:
1. Create a multi_pack_index bit in the packed_git struct that is
one if and only if the pack was loaded from a multi-pack-index.
2. Skip packs with the multi_pack_index bit when doing object
lookups and abbreviations. These algorithms already check the
multi-pack-index before the packed_git struct. This has a very
small performance hit, as we need to walk more packed_git
structs. This is acceptable, since these operations run binary
search on the other packs, so this walk-and-ignore logic is
very fast by comparison.
3. When closing a multi-pack-index file, do not close its packs,
as those packs will be closed using close_all_packs(). In some
cases, such as 'git repack', we run 'close_midx()' without also
closing the packs, so we need to un-set the multi_pack_index bit
in those packs. This is necessary, and caught by running
t6501-freshen-objects.sh with GIT_TEST_MULTI_PACK_INDEX=1.
To manually test this change, I inserted trace2 logging into
close_pack_fd() and set pack_max_fds to 10, then ran 'git rev-list
--all --objects' on a copy of the Git repo with 300+ pack-files and
a multi-pack-index. The logs verified the packs are closed as
we read them beyond the file descriptor limit.
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-04-29 19:18:56 +03:00
|
|
|
if (p->multi_pack_index)
|
|
|
|
return;
|
|
|
|
|
2017-10-12 15:02:20 +03:00
|
|
|
if (open_pack_index(p) || !p->num_objects)
|
|
|
|
return;
|
|
|
|
|
|
|
|
num = p->num_objects;
|
2018-03-22 20:40:10 +03:00
|
|
|
mad_oid = mad->oid;
|
|
|
|
match = bsearch_pack(mad_oid, p, &first);
|
2017-10-12 15:02:20 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* first is now the position in the packfile where we would insert
|
|
|
|
* mad->hash if it does not exist (or the position of mad->hash if
|
2018-02-27 14:47:04 +03:00
|
|
|
* it does exist). Hence, we consider a maximum of two objects
|
2017-10-12 15:02:20 +03:00
|
|
|
* nearby for the abbreviation length.
|
|
|
|
*/
|
|
|
|
mad->init_len = 0;
|
|
|
|
if (!match) {
|
2020-02-24 07:27:36 +03:00
|
|
|
if (!nth_packed_object_id(&oid, p, first))
|
2018-02-27 14:47:04 +03:00
|
|
|
extend_abbrev_len(&oid, mad);
|
2017-10-12 15:02:20 +03:00
|
|
|
} else if (first < num - 1) {
|
2020-02-24 07:27:36 +03:00
|
|
|
if (!nth_packed_object_id(&oid, p, first + 1))
|
2018-02-27 14:47:04 +03:00
|
|
|
extend_abbrev_len(&oid, mad);
|
2017-10-12 15:02:20 +03:00
|
|
|
}
|
|
|
|
if (first > 0) {
|
2020-02-24 07:27:36 +03:00
|
|
|
if (!nth_packed_object_id(&oid, p, first - 1))
|
2018-02-27 14:47:04 +03:00
|
|
|
extend_abbrev_len(&oid, mad);
|
2017-10-12 15:02:20 +03:00
|
|
|
}
|
|
|
|
mad->init_len = mad->cur_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void find_abbrev_len_packed(struct min_abbrev_data *mad)
|
|
|
|
{
|
2018-07-12 22:39:35 +03:00
|
|
|
struct multi_pack_index *m;
|
2017-10-12 15:02:20 +03:00
|
|
|
struct packed_git *p;
|
|
|
|
|
2019-04-16 12:33:21 +03:00
|
|
|
for (m = get_multi_pack_index(mad->repo); m; m = m->next)
|
2018-07-12 22:39:35 +03:00
|
|
|
find_abbrev_len_for_midx(m, mad);
|
2019-04-16 12:33:21 +03:00
|
|
|
for (p = get_packed_git(mad->repo); p; p = p->next)
|
2017-10-12 15:02:20 +03:00
|
|
|
find_abbrev_len_for_pack(p, mad);
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:22 +03:00
|
|
|
int repo_find_unique_abbrev_r(struct repository *r, char *hex,
|
|
|
|
const struct object_id *oid, int len)
|
2017-10-08 21:49:40 +03:00
|
|
|
{
|
|
|
|
struct disambiguate_state ds;
|
|
|
|
struct min_abbrev_data mad;
|
|
|
|
struct object_id oid_ret;
|
2019-04-16 12:33:22 +03:00
|
|
|
const unsigned hexsz = r->hash_algo->hexsz;
|
2018-07-16 04:27:58 +03:00
|
|
|
|
2016-10-01 03:19:37 +03:00
|
|
|
if (len < 0) {
|
2019-04-16 12:33:22 +03:00
|
|
|
unsigned long count = repo_approximate_object_count(r);
|
2016-10-04 02:47:28 +03:00
|
|
|
/*
|
|
|
|
* Add one because the MSB only tells us the highest bit set,
|
|
|
|
* not including the value of all the _other_ bits (so "15"
|
|
|
|
* is only one off of 2^4, but the MSB is the 3rd bit.
|
|
|
|
*/
|
|
|
|
len = msb(count) + 1;
|
|
|
|
/*
|
|
|
|
* We now know we have on the order of 2^len objects, which
|
|
|
|
* expects a collision at 2^(len/2). But we also care about hex
|
|
|
|
* chars, not bits, and there are 4 bits per hex. So all
|
2017-07-08 13:35:35 +03:00
|
|
|
* together we need to divide by 2 and round up.
|
2016-10-04 02:47:28 +03:00
|
|
|
*/
|
2017-07-08 13:35:35 +03:00
|
|
|
len = DIV_ROUND_UP(len, 2);
|
2016-10-04 02:47:28 +03:00
|
|
|
/*
|
|
|
|
* For very small repos, we stick with our regular fallback.
|
|
|
|
*/
|
|
|
|
if (len < FALLBACK_DEFAULT_ABBREV)
|
|
|
|
len = FALLBACK_DEFAULT_ABBREV;
|
2016-10-01 03:19:37 +03:00
|
|
|
}
|
2016-10-04 02:47:28 +03:00
|
|
|
|
2018-03-12 05:27:30 +03:00
|
|
|
oid_to_hex_r(hex, oid);
|
2018-07-16 04:27:58 +03:00
|
|
|
if (len == hexsz || !len)
|
|
|
|
return hexsz;
|
2017-10-08 21:49:40 +03:00
|
|
|
|
2019-04-16 12:33:22 +03:00
|
|
|
mad.repo = r;
|
2017-10-08 21:49:40 +03:00
|
|
|
mad.init_len = len;
|
|
|
|
mad.cur_len = len;
|
|
|
|
mad.hex = hex;
|
2018-03-22 20:40:08 +03:00
|
|
|
mad.oid = oid;
|
2017-10-12 15:02:20 +03:00
|
|
|
|
|
|
|
find_abbrev_len_packed(&mad);
|
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
if (init_object_disambiguation(r, hex, mad.cur_len, &ds) < 0)
|
2017-10-12 15:02:20 +03:00
|
|
|
return -1;
|
2017-10-08 21:49:40 +03:00
|
|
|
|
2019-04-16 12:33:23 +03:00
|
|
|
ds.fn = repo_extend_abbrev_len;
|
2017-10-08 21:49:40 +03:00
|
|
|
ds.always_call_fn = 1;
|
|
|
|
ds.cb_data = (void *)&mad;
|
|
|
|
|
|
|
|
find_short_object_filename(&ds);
|
|
|
|
(void)finish_object_disambiguation(&ds, &oid_ret);
|
|
|
|
|
|
|
|
hex[mad.cur_len] = 0;
|
|
|
|
return mad.cur_len;
|
2015-09-25 00:05:45 +03:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:22 +03:00
|
|
|
const char *repo_find_unique_abbrev(struct repository *r,
|
|
|
|
const struct object_id *oid,
|
|
|
|
int len)
|
2015-09-25 00:05:45 +03:00
|
|
|
{
|
2016-10-20 09:19:19 +03:00
|
|
|
static int bufno;
|
2017-03-26 19:01:24 +03:00
|
|
|
static char hexbuffer[4][GIT_MAX_HEXSZ + 1];
|
2016-11-01 11:49:07 +03:00
|
|
|
char *hex = hexbuffer[bufno];
|
|
|
|
bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
|
2019-04-16 12:33:22 +03:00
|
|
|
repo_find_unique_abbrev_r(r, hex, oid, len);
|
2008-03-02 10:35:32 +03:00
|
|
|
return hex;
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
|
|
|
|
2005-12-15 23:54:00 +03:00
|
|
|
static int ambiguous_path(const char *path, int len)
|
Be more careful about reference parsing
This does two things:
- we don't allow "." and ".." as components of a refname. Thus get_sha1()
will not accept "./refname" as being the same as "refname" any more.
- git-rev-parse stops doing revision translation after seeing a pathname,
to match the brhaviour of all the tools (once we see a pathname,
everything else will also be parsed as a pathname).
Basically, if you did
git log *
and "gitk" was somewhere in the "*", we don't want to replace the filename
"gitk" with the SHA1 of the branch with the same name.
Of course, if there is any change of ambiguity, you should always use "--"
to make it explicit what are filenames and what are revisions, but this
makes the normal cases sane. The refname rule also means that instead of
the "--", you can do the same thing we're used to doing with filenames
that start with a slash: use "./filename" instead, and now it's a
filename, not an option (and not a revision).
So "git log ./*.c" is now actually a perfectly valid thing to do, even if
the first C-file might have the same name as a branch.
Trivial test:
git-rev-parse gitk ./gitk gitk
should output something like
9843c3074dfbf57117565f6b7c93e3e6812857ee
./gitk
gitk
where the "./gitk" isn't seen as a revision, and the second "gitk" is a
filename simply because we've seen filenames already, and thus stopped
doing revision parsing.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-28 23:41:49 +04:00
|
|
|
{
|
|
|
|
int slash = 1;
|
2005-12-15 23:54:00 +03:00
|
|
|
int cnt;
|
Be more careful about reference parsing
This does two things:
- we don't allow "." and ".." as components of a refname. Thus get_sha1()
will not accept "./refname" as being the same as "refname" any more.
- git-rev-parse stops doing revision translation after seeing a pathname,
to match the brhaviour of all the tools (once we see a pathname,
everything else will also be parsed as a pathname).
Basically, if you did
git log *
and "gitk" was somewhere in the "*", we don't want to replace the filename
"gitk" with the SHA1 of the branch with the same name.
Of course, if there is any change of ambiguity, you should always use "--"
to make it explicit what are filenames and what are revisions, but this
makes the normal cases sane. The refname rule also means that instead of
the "--", you can do the same thing we're used to doing with filenames
that start with a slash: use "./filename" instead, and now it's a
filename, not an option (and not a revision).
So "git log ./*.c" is now actually a perfectly valid thing to do, even if
the first C-file might have the same name as a branch.
Trivial test:
git-rev-parse gitk ./gitk gitk
should output something like
9843c3074dfbf57117565f6b7c93e3e6812857ee
./gitk
gitk
where the "./gitk" isn't seen as a revision, and the second "gitk" is a
filename simply because we've seen filenames already, and thus stopped
doing revision parsing.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-28 23:41:49 +04:00
|
|
|
|
2005-12-15 23:54:00 +03:00
|
|
|
for (cnt = 0; cnt < len; cnt++) {
|
Be more careful about reference parsing
This does two things:
- we don't allow "." and ".." as components of a refname. Thus get_sha1()
will not accept "./refname" as being the same as "refname" any more.
- git-rev-parse stops doing revision translation after seeing a pathname,
to match the brhaviour of all the tools (once we see a pathname,
everything else will also be parsed as a pathname).
Basically, if you did
git log *
and "gitk" was somewhere in the "*", we don't want to replace the filename
"gitk" with the SHA1 of the branch with the same name.
Of course, if there is any change of ambiguity, you should always use "--"
to make it explicit what are filenames and what are revisions, but this
makes the normal cases sane. The refname rule also means that instead of
the "--", you can do the same thing we're used to doing with filenames
that start with a slash: use "./filename" instead, and now it's a
filename, not an option (and not a revision).
So "git log ./*.c" is now actually a perfectly valid thing to do, even if
the first C-file might have the same name as a branch.
Trivial test:
git-rev-parse gitk ./gitk gitk
should output something like
9843c3074dfbf57117565f6b7c93e3e6812857ee
./gitk
gitk
where the "./gitk" isn't seen as a revision, and the second "gitk" is a
filename simply because we've seen filenames already, and thus stopped
doing revision parsing.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-28 23:41:49 +04:00
|
|
|
switch (*path++) {
|
|
|
|
case '\0':
|
|
|
|
break;
|
|
|
|
case '/':
|
|
|
|
if (slash)
|
|
|
|
break;
|
|
|
|
slash = 1;
|
|
|
|
continue;
|
|
|
|
case '.':
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
slash = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2005-12-17 11:00:50 +03:00
|
|
|
break;
|
Be more careful about reference parsing
This does two things:
- we don't allow "." and ".." as components of a refname. Thus get_sha1()
will not accept "./refname" as being the same as "refname" any more.
- git-rev-parse stops doing revision translation after seeing a pathname,
to match the brhaviour of all the tools (once we see a pathname,
everything else will also be parsed as a pathname).
Basically, if you did
git log *
and "gitk" was somewhere in the "*", we don't want to replace the filename
"gitk" with the SHA1 of the branch with the same name.
Of course, if there is any change of ambiguity, you should always use "--"
to make it explicit what are filenames and what are revisions, but this
makes the normal cases sane. The refname rule also means that instead of
the "--", you can do the same thing we're used to doing with filenames
that start with a slash: use "./filename" instead, and now it's a
filename, not an option (and not a revision).
So "git log ./*.c" is now actually a perfectly valid thing to do, even if
the first C-file might have the same name as a branch.
Trivial test:
git-rev-parse gitk ./gitk gitk
should output something like
9843c3074dfbf57117565f6b7c93e3e6812857ee
./gitk
gitk
where the "./gitk" isn't seen as a revision, and the second "gitk" is a
filename simply because we've seen filenames already, and thus stopped
doing revision parsing.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-28 23:41:49 +04:00
|
|
|
}
|
2005-12-15 23:54:00 +03:00
|
|
|
return slash;
|
Be more careful about reference parsing
This does two things:
- we don't allow "." and ".." as components of a refname. Thus get_sha1()
will not accept "./refname" as being the same as "refname" any more.
- git-rev-parse stops doing revision translation after seeing a pathname,
to match the brhaviour of all the tools (once we see a pathname,
everything else will also be parsed as a pathname).
Basically, if you did
git log *
and "gitk" was somewhere in the "*", we don't want to replace the filename
"gitk" with the SHA1 of the branch with the same name.
Of course, if there is any change of ambiguity, you should always use "--"
to make it explicit what are filenames and what are revisions, but this
makes the normal cases sane. The refname rule also means that instead of
the "--", you can do the same thing we're used to doing with filenames
that start with a slash: use "./filename" instead, and now it's a
filename, not an option (and not a revision).
So "git log ./*.c" is now actually a perfectly valid thing to do, even if
the first C-file might have the same name as a branch.
Trivial test:
git-rev-parse gitk ./gitk gitk
should output something like
9843c3074dfbf57117565f6b7c93e3e6812857ee
./gitk
gitk
where the "./gitk" isn't seen as a revision, and the second "gitk" is a
filename simply because we've seen filenames already, and thus stopped
doing revision parsing.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-28 23:41:49 +04:00
|
|
|
}
|
|
|
|
|
2015-05-21 07:45:39 +03:00
|
|
|
static inline int at_mark(const char *string, int len,
|
|
|
|
const char **suffix, int nr)
|
2010-01-20 10:17:11 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2015-05-21 07:45:39 +03:00
|
|
|
for (i = 0; i < nr; i++) {
|
2010-01-20 10:17:11 +03:00
|
|
|
int suffix_len = strlen(suffix[i]);
|
|
|
|
if (suffix_len <= len
|
2017-03-27 14:16:55 +03:00
|
|
|
&& !strncasecmp(string, suffix[i], suffix_len))
|
2010-01-20 10:17:11 +03:00
|
|
|
return suffix_len;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-21 07:45:39 +03:00
|
|
|
static inline int upstream_mark(const char *string, int len)
|
|
|
|
{
|
|
|
|
const char *suffix[] = { "@{upstream}", "@{u}" };
|
|
|
|
return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
|
|
|
|
}
|
|
|
|
|
sha1_name: implement @{push} shorthand
In a triangular workflow, each branch may have two distinct
points of interest: the @{upstream} that you normally pull
from, and the destination that you normally push to. There
isn't a shorthand for the latter, but it's useful to have.
For instance, you may want to know which commits you haven't
pushed yet:
git log @{push}..
Or as a more complicated example, imagine that you normally
pull changes from origin/master (which you set as your
@{upstream}), and push changes to your own personal fork
(e.g., as myfork/topic). You may push to your fork from
multiple machines, requiring you to integrate the changes
from the push destination, rather than upstream. With this
patch, you can just do:
git rebase @{push}
rather than typing out the full name.
The heavy lifting is all done by branch_get_push; here we
just wire it up to the "@{push}" syntax.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-21 07:45:47 +03:00
|
|
|
static inline int push_mark(const char *string, int len)
|
|
|
|
{
|
|
|
|
const char *suffix[] = { "@{push}" };
|
|
|
|
return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
static enum get_oid_result get_oid_1(struct repository *r, const char *name, int len, struct object_id *oid, unsigned lookup_flags);
|
2019-04-16 12:33:26 +03:00
|
|
|
static int interpret_nth_prior_checkout(struct repository *r, const char *name, int namelen, struct strbuf *buf);
|
2009-01-17 19:09:55 +03:00
|
|
|
|
2019-04-16 12:33:31 +03:00
|
|
|
static int get_oid_basic(struct repository *r, const char *str, int len,
|
|
|
|
struct object_id *oid, unsigned int flags)
|
2007-01-19 12:15:15 +03:00
|
|
|
{
|
2010-08-24 08:52:43 +04:00
|
|
|
static const char *warn_msg = "refname '%.*s' is ambiguous.";
|
2013-05-29 16:12:42 +04:00
|
|
|
static const char *object_name_msg = N_(
|
|
|
|
"Git normally never creates a ref that ends with 40 hex characters\n"
|
|
|
|
"because it will be ignored when you just specify 40-hex. These refs\n"
|
|
|
|
"may be created by mistake. For example,\n"
|
|
|
|
"\n"
|
2019-03-29 13:39:19 +03:00
|
|
|
" git switch -c $br $(git rev-parse ...)\n"
|
2013-05-29 16:12:42 +04:00
|
|
|
"\n"
|
|
|
|
"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
|
|
|
|
"examine these refs and maybe delete them. Turn this message off by\n"
|
2013-08-01 00:23:31 +04:00
|
|
|
"running \"git config advice.objectNameWarning false\"");
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
struct object_id tmp_oid;
|
2006-09-12 07:17:35 +04:00
|
|
|
char *real_ref = NULL;
|
2006-10-06 10:16:15 +04:00
|
|
|
int refs_found = 0;
|
2013-05-08 01:55:10 +04:00
|
|
|
int at, reflog_len, nth_prior = 0;
|
2005-08-04 09:15:49 +04:00
|
|
|
|
2019-04-16 12:33:31 +03:00
|
|
|
if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
|
2014-01-07 07:32:01 +04:00
|
|
|
if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
|
2020-09-02 01:28:09 +03:00
|
|
|
refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
|
2014-01-07 07:32:01 +04:00
|
|
|
if (refs_found > 0) {
|
cat-file: disable object/refname ambiguity check for batch mode
A common use of "cat-file --batch-check" is to feed a list
of objects from "rev-list --objects" or a similar command.
In this instance, all of our input objects are 40-byte sha1
ids. However, cat-file has always allowed arbitrary revision
specifiers, and feeds the result to get_sha1().
Fortunately, get_sha1() recognizes a 40-byte sha1 before
doing any hard work trying to look up refs, meaning this
scenario should end up spending very little time converting
the input into an object sha1. However, since 798c35f
(get_sha1: warn about full or short object names that look
like refs, 2013-05-29), when we encounter this case, we
spend the extra effort to do a refname lookup anyway, just
to print a warning. This is further exacerbated by ca91993
(get_packed_ref_cache: reload packed-refs file when it
changes, 2013-06-20), which makes individual ref lookup more
expensive by requiring a stat() of the packed-refs file for
each missing ref.
With no patches, this is the time it takes to run:
$ git rev-list --objects --all >objects
$ time git cat-file --batch-check='%(objectname)' <objects
on the linux.git repository:
real 1m13.494s
user 0m25.924s
sys 0m47.532s
If we revert ca91993, the packed-refs up-to-date check, it
gets a little better:
real 0m54.697s
user 0m21.692s
sys 0m32.916s
but we are still spending quite a bit of time on ref lookup
(and we would not want to revert that patch, anyway, which
has correctness issues). If we revert 798c35f, disabling
the warning entirely, we get a much more reasonable time:
real 0m7.452s
user 0m6.836s
sys 0m0.608s
This patch does the moral equivalent of this final case (and
gets similar speedups). We introduce a global flag that
callers of get_sha1() can use to avoid paying the price for
the warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-12 10:20:05 +04:00
|
|
|
warning(warn_msg, len, str);
|
|
|
|
if (advice_object_name_warning)
|
|
|
|
fprintf(stderr, "%s\n", _(object_name_msg));
|
|
|
|
}
|
|
|
|
free(real_ref);
|
2013-05-29 16:12:42 +04:00
|
|
|
}
|
2005-08-04 09:15:49 +04:00
|
|
|
return 0;
|
2013-05-29 16:12:42 +04:00
|
|
|
}
|
2005-08-04 09:15:49 +04:00
|
|
|
|
2009-01-17 19:09:55 +03:00
|
|
|
/* basic@{time or number or -number} format to query ref-log */
|
2006-10-24 08:15:34 +04:00
|
|
|
reflog_len = at = 0;
|
2009-01-28 02:07:46 +03:00
|
|
|
if (len && str[len-1] == '}') {
|
2013-05-08 01:55:09 +04:00
|
|
|
for (at = len-4; at >= 0; at--) {
|
2006-10-06 10:16:15 +04:00
|
|
|
if (str[at] == '@' && str[at+1] == '{') {
|
2013-05-08 01:55:11 +04:00
|
|
|
if (str[at+2] == '-') {
|
|
|
|
if (at != 0)
|
|
|
|
/* @{-N} not at start */
|
|
|
|
return -1;
|
2013-05-08 01:55:10 +04:00
|
|
|
nth_prior = 1;
|
|
|
|
continue;
|
|
|
|
}
|
sha1_name: implement @{push} shorthand
In a triangular workflow, each branch may have two distinct
points of interest: the @{upstream} that you normally pull
from, and the destination that you normally push to. There
isn't a shorthand for the latter, but it's useful to have.
For instance, you may want to know which commits you haven't
pushed yet:
git log @{push}..
Or as a more complicated example, imagine that you normally
pull changes from origin/master (which you set as your
@{upstream}), and push changes to your own personal fork
(e.g., as myfork/topic). You may push to your fork from
multiple machines, requiring you to integrate the changes
from the push destination, rather than upstream. With this
patch, you can just do:
git rebase @{push}
rather than typing out the full name.
The heavy lifting is all done by branch_get_push; here we
just wire it up to the "@{push}" syntax.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-21 07:45:47 +03:00
|
|
|
if (!upstream_mark(str + at, len - at) &&
|
|
|
|
!push_mark(str + at, len - at)) {
|
2009-09-10 19:25:57 +04:00
|
|
|
reflog_len = (len-1) - (at+2);
|
|
|
|
len = at;
|
|
|
|
}
|
2006-10-06 10:16:15 +04:00
|
|
|
break;
|
|
|
|
}
|
2006-05-17 13:56:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Be more careful about reference parsing
This does two things:
- we don't allow "." and ".." as components of a refname. Thus get_sha1()
will not accept "./refname" as being the same as "refname" any more.
- git-rev-parse stops doing revision translation after seeing a pathname,
to match the brhaviour of all the tools (once we see a pathname,
everything else will also be parsed as a pathname).
Basically, if you did
git log *
and "gitk" was somewhere in the "*", we don't want to replace the filename
"gitk" with the SHA1 of the branch with the same name.
Of course, if there is any change of ambiguity, you should always use "--"
to make it explicit what are filenames and what are revisions, but this
makes the normal cases sane. The refname rule also means that instead of
the "--", you can do the same thing we're used to doing with filenames
that start with a slash: use "./filename" instead, and now it's a
filename, not an option (and not a revision).
So "git log ./*.c" is now actually a perfectly valid thing to do, even if
the first C-file might have the same name as a branch.
Trivial test:
git-rev-parse gitk ./gitk gitk
should output something like
9843c3074dfbf57117565f6b7c93e3e6812857ee
./gitk
gitk
where the "./gitk" isn't seen as a revision, and the second "gitk" is a
filename simply because we've seen filenames already, and thus stopped
doing revision parsing.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-28 23:41:49 +04:00
|
|
|
/* Accept only unambiguous ref paths. */
|
2007-02-02 01:29:33 +03:00
|
|
|
if (len && ambiguous_path(str, len))
|
Be more careful about reference parsing
This does two things:
- we don't allow "." and ".." as components of a refname. Thus get_sha1()
will not accept "./refname" as being the same as "refname" any more.
- git-rev-parse stops doing revision translation after seeing a pathname,
to match the brhaviour of all the tools (once we see a pathname,
everything else will also be parsed as a pathname).
Basically, if you did
git log *
and "gitk" was somewhere in the "*", we don't want to replace the filename
"gitk" with the SHA1 of the branch with the same name.
Of course, if there is any change of ambiguity, you should always use "--"
to make it explicit what are filenames and what are revisions, but this
makes the normal cases sane. The refname rule also means that instead of
the "--", you can do the same thing we're used to doing with filenames
that start with a slash: use "./filename" instead, and now it's a
filename, not an option (and not a revision).
So "git log ./*.c" is now actually a perfectly valid thing to do, even if
the first C-file might have the same name as a branch.
Trivial test:
git-rev-parse gitk ./gitk gitk
should output something like
9843c3074dfbf57117565f6b7c93e3e6812857ee
./gitk
gitk
where the "./gitk" isn't seen as a revision, and the second "gitk" is a
filename simply because we've seen filenames already, and thus stopped
doing revision parsing.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-28 23:41:49 +04:00
|
|
|
return -1;
|
|
|
|
|
2013-05-08 01:55:10 +04:00
|
|
|
if (nth_prior) {
|
2009-01-17 19:09:55 +03:00
|
|
|
struct strbuf buf = STRBUF_INIT;
|
2013-05-08 01:55:10 +04:00
|
|
|
int detached;
|
|
|
|
|
2019-04-16 12:33:31 +03:00
|
|
|
if (interpret_nth_prior_checkout(r, str, len, &buf) > 0) {
|
|
|
|
detached = (buf.len == r->hash_algo->hexsz && !get_oid_hex(buf.buf, oid));
|
2013-05-08 01:55:10 +04:00
|
|
|
strbuf_release(&buf);
|
|
|
|
if (detached)
|
|
|
|
return 0;
|
2009-01-17 19:09:55 +03:00
|
|
|
}
|
2013-05-08 01:55:10 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!len && reflog_len)
|
2007-02-02 01:29:33 +03:00
|
|
|
/* allow "@{...}" to mean the current branch reflog */
|
2020-09-02 01:28:09 +03:00
|
|
|
refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref, 0);
|
2013-05-08 01:55:10 +04:00
|
|
|
else if (reflog_len)
|
2019-04-16 12:33:31 +03:00
|
|
|
refs_found = repo_dwim_log(r, str, len, oid, &real_ref);
|
2007-02-04 05:49:16 +03:00
|
|
|
else
|
2020-09-02 01:28:09 +03:00
|
|
|
refs_found = repo_dwim_ref(r, str, len, oid, &real_ref, 0);
|
2006-05-17 13:56:09 +04:00
|
|
|
|
|
|
|
if (!refs_found)
|
|
|
|
return -1;
|
|
|
|
|
2017-07-14 02:49:29 +03:00
|
|
|
if (warn_ambiguous_refs && !(flags & GET_OID_QUIETLY) &&
|
2013-05-29 16:12:42 +04:00
|
|
|
(refs_found > 1 ||
|
2019-04-16 12:33:31 +03:00
|
|
|
!get_short_oid(r, str, len, &tmp_oid, GET_OID_QUIETLY)))
|
2010-08-24 08:52:43 +04:00
|
|
|
warning(warn_msg, len, str);
|
2006-05-17 13:56:09 +04:00
|
|
|
|
2006-10-06 10:16:15 +04:00
|
|
|
if (reflog_len) {
|
|
|
|
int nth, i;
|
2017-04-26 22:29:31 +03:00
|
|
|
timestamp_t at_time;
|
|
|
|
timestamp_t co_time;
|
2007-01-19 12:19:05 +03:00
|
|
|
int co_tz, co_cnt;
|
|
|
|
|
2007-02-01 20:33:23 +03:00
|
|
|
/* Is it asking for N-th entry, or approxidate? */
|
2006-10-06 10:16:15 +04:00
|
|
|
for (i = nth = 0; 0 <= nth && i < reflog_len; i++) {
|
|
|
|
char ch = str[at+2+i];
|
|
|
|
if ('0' <= ch && ch <= '9')
|
|
|
|
nth = nth * 10 + ch - '0';
|
|
|
|
else
|
|
|
|
nth = -1;
|
|
|
|
}
|
2008-08-21 19:40:44 +04:00
|
|
|
if (100000000 <= nth) {
|
|
|
|
at_time = nth;
|
|
|
|
nth = -1;
|
|
|
|
} else if (0 <= nth)
|
2006-10-06 10:16:15 +04:00
|
|
|
at_time = 0;
|
2008-04-30 08:13:58 +04:00
|
|
|
else {
|
2010-01-26 22:58:00 +03:00
|
|
|
int errors = 0;
|
2008-04-30 08:13:58 +04:00
|
|
|
char *tmp = xstrndup(str + at + 2, reflog_len);
|
2010-01-26 22:58:00 +03:00
|
|
|
at_time = approxidate_careful(tmp, &errors);
|
2008-04-30 08:13:58 +04:00
|
|
|
free(tmp);
|
2014-07-24 08:41:11 +04:00
|
|
|
if (errors) {
|
|
|
|
free(real_ref);
|
2010-01-27 21:53:09 +03:00
|
|
|
return -1;
|
2014-07-24 08:41:11 +04:00
|
|
|
}
|
2008-04-30 08:13:58 +04:00
|
|
|
}
|
2019-04-16 12:33:31 +03:00
|
|
|
if (read_ref_at(get_main_ref_store(r),
|
2019-04-06 14:34:30 +03:00
|
|
|
real_ref, flags, at_time, nth, oid, NULL,
|
2007-01-19 12:19:05 +03:00
|
|
|
&co_time, &co_tz, &co_cnt)) {
|
2013-05-22 14:39:55 +04:00
|
|
|
if (!len) {
|
2020-01-30 22:35:46 +03:00
|
|
|
if (!skip_prefix(real_ref, "refs/heads/", &str))
|
2013-05-22 14:39:55 +04:00
|
|
|
str = "HEAD";
|
2020-01-30 22:35:46 +03:00
|
|
|
len = strlen(str);
|
2013-05-22 14:39:55 +04:00
|
|
|
}
|
2014-09-19 07:45:37 +04:00
|
|
|
if (at_time) {
|
2017-07-14 02:49:29 +03:00
|
|
|
if (!(flags & GET_OID_QUIETLY)) {
|
2020-01-25 03:13:01 +03:00
|
|
|
warning(_("log for '%.*s' only goes back to %s"),
|
|
|
|
len, str,
|
convert "enum date_mode" into a struct
In preparation for adding date modes that may carry extra
information beyond the mode itself, this patch converts the
date_mode enum into a struct.
Most of the conversion is fairly straightforward; we pass
the struct as a pointer and dereference the type field where
necessary. Locations that declare a date_mode can use a "{}"
constructor. However, the tricky case is where we use the
enum labels as constants, like:
show_date(t, tz, DATE_NORMAL);
Ideally we could say:
show_date(t, tz, &{ DATE_NORMAL });
but of course C does not allow that. Likewise, we cannot
cast the constant to a struct, because we need to pass an
actual address. Our options are basically:
1. Manually add a "struct date_mode d = { DATE_NORMAL }"
definition to each caller, and pass "&d". This makes
the callers uglier, because they sometimes do not even
have their own scope (e.g., they are inside a switch
statement).
2. Provide a pre-made global "date_normal" struct that can
be passed by address. We'd also need "date_rfc2822",
"date_iso8601", and so forth. But at least the ugliness
is defined in one place.
3. Provide a wrapper that generates the correct struct on
the fly. The big downside is that we end up pointing to
a single global, which makes our wrapper non-reentrant.
But show_date is already not reentrant, so it does not
matter.
This patch implements 3, along with a minor macro to keep
the size of the callers sane.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-25 19:55:02 +03:00
|
|
|
show_date(co_time, co_tz, DATE_MODE(RFC2822)));
|
2014-09-19 07:45:37 +04:00
|
|
|
}
|
|
|
|
} else {
|
2017-07-14 02:49:29 +03:00
|
|
|
if (flags & GET_OID_QUIETLY) {
|
2014-09-19 07:45:37 +04:00
|
|
|
exit(128);
|
|
|
|
}
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("log for '%.*s' only has %d entries"),
|
2010-08-24 08:52:42 +04:00
|
|
|
len, str, co_cnt);
|
|
|
|
}
|
2007-01-19 12:19:05 +03:00
|
|
|
}
|
2006-05-17 13:56:09 +04:00
|
|
|
}
|
|
|
|
|
2006-09-12 07:17:35 +04:00
|
|
|
free(real_ref);
|
2006-05-17 13:56:09 +04:00
|
|
|
return 0;
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
static enum get_oid_result get_parent(struct repository *r,
|
|
|
|
const char *name, int len,
|
2019-01-18 07:19:43 +03:00
|
|
|
struct object_id *result, int idx)
|
2005-08-04 09:15:49 +04:00
|
|
|
{
|
2017-05-07 01:10:09 +03:00
|
|
|
struct object_id oid;
|
2019-04-16 12:33:32 +03:00
|
|
|
enum get_oid_result ret = get_oid_1(r, name, len, &oid,
|
2019-01-18 07:19:43 +03:00
|
|
|
GET_OID_COMMITTISH);
|
2005-08-04 09:15:49 +04:00
|
|
|
struct commit *commit;
|
|
|
|
struct commit_list *p;
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2019-04-16 12:33:32 +03:00
|
|
|
commit = lookup_commit_reference(r, &oid);
|
2005-08-04 09:15:49 +04:00
|
|
|
if (parse_commit(commit))
|
2019-01-18 07:19:43 +03:00
|
|
|
return MISSING_OBJECT;
|
2005-08-04 09:15:49 +04:00
|
|
|
if (!idx) {
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oidcpy(result, &commit->object.oid);
|
2019-01-18 07:19:43 +03:00
|
|
|
return FOUND;
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
|
|
|
p = commit->parents;
|
|
|
|
while (p) {
|
|
|
|
if (!--idx) {
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oidcpy(result, &p->item->object.oid);
|
2019-01-18 07:19:43 +03:00
|
|
|
return FOUND;
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
|
|
|
p = p->next;
|
|
|
|
}
|
2019-01-18 07:19:43 +03:00
|
|
|
return MISSING_OBJECT;
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
static enum get_oid_result get_nth_ancestor(struct repository *r,
|
|
|
|
const char *name, int len,
|
2019-01-18 07:19:43 +03:00
|
|
|
struct object_id *result,
|
|
|
|
int generation)
|
2005-08-21 13:43:54 +04:00
|
|
|
{
|
2017-05-07 01:10:09 +03:00
|
|
|
struct object_id oid;
|
2008-03-14 21:49:40 +03:00
|
|
|
struct commit *commit;
|
|
|
|
int ret;
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
ret = get_oid_1(r, name, len, &oid, GET_OID_COMMITTISH);
|
2005-08-21 13:43:54 +04:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2019-04-16 12:33:32 +03:00
|
|
|
commit = lookup_commit_reference(r, &oid);
|
2008-03-14 21:49:40 +03:00
|
|
|
if (!commit)
|
2019-01-18 07:19:43 +03:00
|
|
|
return MISSING_OBJECT;
|
2005-08-21 13:43:54 +04:00
|
|
|
|
|
|
|
while (generation--) {
|
2008-03-14 21:49:40 +03:00
|
|
|
if (parse_commit(commit) || !commit->parents)
|
2019-01-18 07:19:43 +03:00
|
|
|
return MISSING_OBJECT;
|
2008-03-14 21:49:40 +03:00
|
|
|
commit = commit->parents->item;
|
2005-08-21 13:43:54 +04:00
|
|
|
}
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oidcpy(result, &commit->object.oid);
|
2019-01-18 07:19:43 +03:00
|
|
|
return FOUND;
|
2005-08-21 13:43:54 +04:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
struct object *repo_peel_to_type(struct repository *r, const char *name, int namelen,
|
|
|
|
struct object *o, enum object_type expected_type)
|
2007-12-24 11:51:01 +03:00
|
|
|
{
|
|
|
|
if (name && !namelen)
|
|
|
|
namelen = strlen(name);
|
|
|
|
while (1) {
|
2019-04-16 12:33:32 +03:00
|
|
|
if (!o || (!o->parsed && !parse_object(r, &o->oid)))
|
2007-12-24 11:51:01 +03:00
|
|
|
return NULL;
|
2013-04-01 02:24:12 +04:00
|
|
|
if (expected_type == OBJ_ANY || o->type == expected_type)
|
2007-12-24 11:51:01 +03:00
|
|
|
return o;
|
|
|
|
if (o->type == OBJ_TAG)
|
|
|
|
o = ((struct tag*) o)->tagged;
|
|
|
|
else if (o->type == OBJ_COMMIT)
|
2019-04-16 12:33:32 +03:00
|
|
|
o = &(repo_get_commit_tree(r, ((struct commit *)o))->object);
|
2007-12-24 11:51:01 +03:00
|
|
|
else {
|
|
|
|
if (name)
|
|
|
|
error("%.*s: expected %s type, but the object "
|
|
|
|
"dereferences to %s type",
|
2018-02-14 21:59:24 +03:00
|
|
|
namelen, name, type_name(expected_type),
|
|
|
|
type_name(o->type));
|
2007-12-24 11:51:01 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
static int peel_onion(struct repository *r, const char *name, int len,
|
|
|
|
struct object_id *oid, unsigned lookup_flags)
|
2005-10-14 05:57:40 +04:00
|
|
|
{
|
2017-05-07 01:10:29 +03:00
|
|
|
struct object_id outer;
|
2005-10-14 05:57:40 +04:00
|
|
|
const char *sp;
|
Shrink "struct object" a bit
This shrinks "struct object" by a small amount, by getting rid of the
"struct type *" pointer and replacing it with a 3-bit bitfield instead.
In addition, we merge the bitfields and the "flags" field, which
incidentally should also remove a useless 4-byte padding from the object
when in 64-bit mode.
Now, our "struct object" is still too damn large, but it's now less
obviously bloated, and of the remaining fields, only the "util" (which is
not used by most things) is clearly something that should be eventually
discarded.
This shrinks the "git-rev-list --all" memory use by about 2.5% on the
kernel archive (and, perhaps more importantly, on the larger mozilla
archive). That may not sound like much, but I suspect it's more on a
64-bit platform.
There are other remaining inefficiencies (the parent lists, for example,
probably have horrible malloc overhead), but this was pretty obvious.
Most of the patch is just changing the comparison of the "type" pointer
from one of the constant string pointers to the appropriate new TYPE_xxx
small integer constant.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-15 03:45:13 +04:00
|
|
|
unsigned int expected_type = 0;
|
2005-10-14 05:57:40 +04:00
|
|
|
struct object *o;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "ref^{type}" dereferences ref repeatedly until you cannot
|
|
|
|
* dereference anymore, or you get an object of given type,
|
|
|
|
* whichever comes first. "ref^{}" means just dereference
|
|
|
|
* tags until you get a non-tag. "ref^0" is a shorthand for
|
|
|
|
* "ref^{commit}". "commit^{tree}" could be used to find the
|
|
|
|
* top-level tree of the given commit.
|
|
|
|
*/
|
|
|
|
if (len < 4 || name[len-1] != '}')
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (sp = name + len - 1; name <= sp; sp--) {
|
|
|
|
int ch = *sp;
|
|
|
|
if (ch == '{' && name < sp && sp[-1] == '^')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (sp <= name)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
sp++; /* beginning of type name, or closing brace for empty */
|
2013-12-01 00:55:40 +04:00
|
|
|
if (starts_with(sp, "commit}"))
|
2006-07-12 07:45:31 +04:00
|
|
|
expected_type = OBJ_COMMIT;
|
2013-12-01 00:55:40 +04:00
|
|
|
else if (starts_with(sp, "tag}"))
|
2013-09-03 23:50:16 +04:00
|
|
|
expected_type = OBJ_TAG;
|
2013-12-01 00:55:40 +04:00
|
|
|
else if (starts_with(sp, "tree}"))
|
2006-07-12 07:45:31 +04:00
|
|
|
expected_type = OBJ_TREE;
|
2013-12-01 00:55:40 +04:00
|
|
|
else if (starts_with(sp, "blob}"))
|
2006-07-12 07:45:31 +04:00
|
|
|
expected_type = OBJ_BLOB;
|
2013-12-01 00:55:40 +04:00
|
|
|
else if (starts_with(sp, "object}"))
|
2013-04-01 02:24:12 +04:00
|
|
|
expected_type = OBJ_ANY;
|
2005-10-14 05:57:40 +04:00
|
|
|
else if (sp[0] == '}')
|
2006-07-12 07:45:31 +04:00
|
|
|
expected_type = OBJ_NONE;
|
2010-12-13 06:01:15 +03:00
|
|
|
else if (sp[0] == '/')
|
|
|
|
expected_type = OBJ_COMMIT;
|
2005-10-14 05:57:40 +04:00
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
2017-07-14 02:49:29 +03:00
|
|
|
lookup_flags &= ~GET_OID_DISAMBIGUATORS;
|
2012-07-02 21:00:40 +04:00
|
|
|
if (expected_type == OBJ_COMMIT)
|
2017-07-14 02:49:29 +03:00
|
|
|
lookup_flags |= GET_OID_COMMITTISH;
|
2013-04-01 02:19:52 +04:00
|
|
|
else if (expected_type == OBJ_TREE)
|
2017-07-14 02:49:29 +03:00
|
|
|
lookup_flags |= GET_OID_TREEISH;
|
2012-07-02 21:00:40 +04:00
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
if (get_oid_1(r, name, sp - name - 2, &outer, lookup_flags))
|
2005-10-14 05:57:40 +04:00
|
|
|
return -1;
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
o = parse_object(r, &outer);
|
2005-10-14 05:57:40 +04:00
|
|
|
if (!o)
|
|
|
|
return -1;
|
Shrink "struct object" a bit
This shrinks "struct object" by a small amount, by getting rid of the
"struct type *" pointer and replacing it with a 3-bit bitfield instead.
In addition, we merge the bitfields and the "flags" field, which
incidentally should also remove a useless 4-byte padding from the object
when in 64-bit mode.
Now, our "struct object" is still too damn large, but it's now less
obviously bloated, and of the remaining fields, only the "util" (which is
not used by most things) is clearly something that should be eventually
discarded.
This shrinks the "git-rev-list --all" memory use by about 2.5% on the
kernel archive (and, perhaps more importantly, on the larger mozilla
archive). That may not sound like much, but I suspect it's more on a
64-bit platform.
There are other remaining inefficiencies (the parent lists, for example,
probably have horrible malloc overhead), but this was pretty obvious.
Most of the patch is just changing the comparison of the "type" pointer
from one of the constant string pointers to the appropriate new TYPE_xxx
small integer constant.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-06-15 03:45:13 +04:00
|
|
|
if (!expected_type) {
|
2019-04-16 12:33:32 +03:00
|
|
|
o = deref_tag(r, o, name, sp - name - 2);
|
|
|
|
if (!o || (!o->parsed && !parse_object(r, &o->oid)))
|
2005-10-20 09:48:16 +04:00
|
|
|
return -1;
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oidcpy(oid, &o->oid);
|
2010-12-13 06:01:15 +03:00
|
|
|
return 0;
|
2005-10-14 05:57:40 +04:00
|
|
|
}
|
2010-12-13 06:01:15 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* At this point, the syntax look correct, so
|
|
|
|
* if we do not get the needed object, we should
|
|
|
|
* barf.
|
|
|
|
*/
|
2019-04-16 12:33:32 +03:00
|
|
|
o = repo_peel_to_type(r, name, len, o, expected_type);
|
2010-12-13 06:01:15 +03:00
|
|
|
if (!o)
|
2007-12-24 11:51:01 +03:00
|
|
|
return -1;
|
2010-12-13 06:01:15 +03:00
|
|
|
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oidcpy(oid, &o->oid);
|
2010-12-13 06:01:15 +03:00
|
|
|
if (sp[0] == '/') {
|
|
|
|
/* "$commit^{/foo}" */
|
|
|
|
char *prefix;
|
|
|
|
int ret;
|
|
|
|
struct commit_list *list = NULL;
|
|
|
|
|
2007-12-24 11:51:01 +03:00
|
|
|
/*
|
2010-12-15 12:02:54 +03:00
|
|
|
* $commit^{/}. Some regex implementation may reject.
|
|
|
|
* We don't need regex anyway. '' pattern always matches.
|
2005-10-14 05:57:40 +04:00
|
|
|
*/
|
2010-12-15 12:02:54 +03:00
|
|
|
if (sp[1] == '}')
|
2007-12-24 11:51:01 +03:00
|
|
|
return 0;
|
2010-12-15 12:02:54 +03:00
|
|
|
|
2010-12-13 06:01:15 +03:00
|
|
|
prefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));
|
|
|
|
commit_list_insert((struct commit *)o, &list);
|
2019-04-16 12:33:32 +03:00
|
|
|
ret = get_oid_oneline(r, prefix, oid, list);
|
2010-12-13 06:01:15 +03:00
|
|
|
free(prefix);
|
|
|
|
return ret;
|
2005-10-14 05:57:40 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:30 +03:00
|
|
|
static int get_describe_name(struct repository *r,
|
|
|
|
const char *name, int len,
|
|
|
|
struct object_id *oid)
|
2006-09-21 03:11:08 +04:00
|
|
|
{
|
|
|
|
const char *cp;
|
2017-07-14 02:49:29 +03:00
|
|
|
unsigned flags = GET_OID_QUIETLY | GET_OID_COMMIT;
|
2006-09-21 03:11:08 +04:00
|
|
|
|
|
|
|
for (cp = name + len - 1; name + 2 <= cp; cp--) {
|
|
|
|
char ch = *cp;
|
2015-03-10 01:46:54 +03:00
|
|
|
if (!isxdigit(ch)) {
|
2006-09-21 03:11:08 +04:00
|
|
|
/* We must be looking at g in "SOMETHING-g"
|
|
|
|
* for it to be describe output.
|
|
|
|
*/
|
|
|
|
if (ch == 'g' && cp[-1] == '-') {
|
|
|
|
cp++;
|
|
|
|
len -= cp - name;
|
2019-04-16 12:33:30 +03:00
|
|
|
return get_short_oid(r,
|
2019-04-16 12:33:25 +03:00
|
|
|
cp, len, oid, flags);
|
2006-09-21 03:11:08 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
static enum get_oid_result get_oid_1(struct repository *r,
|
|
|
|
const char *name, int len,
|
2019-01-18 07:19:43 +03:00
|
|
|
struct object_id *oid,
|
|
|
|
unsigned lookup_flags)
|
2005-08-04 09:15:49 +04:00
|
|
|
{
|
2006-02-03 10:48:36 +03:00
|
|
|
int ret, has_suffix;
|
2005-08-21 13:43:54 +04:00
|
|
|
const char *cp;
|
2005-08-04 09:15:49 +04:00
|
|
|
|
2008-03-14 21:49:40 +03:00
|
|
|
/*
|
|
|
|
* "name~3" is "name^^^", "name~" is "name~1", and "name^" is "name^1".
|
2005-08-21 13:43:54 +04:00
|
|
|
*/
|
2006-02-03 10:48:36 +03:00
|
|
|
has_suffix = 0;
|
2005-08-21 13:43:54 +04:00
|
|
|
for (cp = name + len - 1; name <= cp; cp--) {
|
|
|
|
int ch = *cp;
|
|
|
|
if ('0' <= ch && ch <= '9')
|
|
|
|
continue;
|
2006-02-03 10:48:36 +03:00
|
|
|
if (ch == '~' || ch == '^')
|
|
|
|
has_suffix = ch;
|
2005-08-21 13:43:54 +04:00
|
|
|
break;
|
|
|
|
}
|
2006-02-03 10:48:36 +03:00
|
|
|
|
|
|
|
if (has_suffix) {
|
2019-09-15 15:10:28 +03:00
|
|
|
unsigned int num = 0;
|
2005-08-21 13:43:54 +04:00
|
|
|
int len1 = cp - name;
|
|
|
|
cp++;
|
2019-09-15 15:10:28 +03:00
|
|
|
while (cp < name + len) {
|
|
|
|
unsigned int digit = *cp++ - '0';
|
|
|
|
if (unsigned_mult_overflows(num, 10))
|
|
|
|
return MISSING_OBJECT;
|
|
|
|
num *= 10;
|
|
|
|
if (unsigned_add_overflows(num, digit))
|
|
|
|
return MISSING_OBJECT;
|
|
|
|
num += digit;
|
|
|
|
}
|
2008-03-14 21:49:40 +03:00
|
|
|
if (!num && len1 == len - 1)
|
|
|
|
num = 1;
|
2019-09-15 15:10:28 +03:00
|
|
|
else if (num > INT_MAX)
|
|
|
|
return MISSING_OBJECT;
|
2008-03-14 21:49:40 +03:00
|
|
|
if (has_suffix == '^')
|
2019-04-16 12:33:32 +03:00
|
|
|
return get_parent(r, name, len1, oid, num);
|
2006-02-03 10:48:36 +03:00
|
|
|
/* else if (has_suffix == '~') -- goes without saying */
|
2019-04-16 12:33:32 +03:00
|
|
|
return get_nth_ancestor(r, name, len1, oid, num);
|
2005-08-21 13:43:54 +04:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
ret = peel_onion(r, name, len, oid, lookup_flags);
|
2005-10-14 05:57:40 +04:00
|
|
|
if (!ret)
|
2019-01-18 07:19:43 +03:00
|
|
|
return FOUND;
|
2005-10-14 05:57:40 +04:00
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
ret = get_oid_basic(r, name, len, oid, lookup_flags);
|
2005-08-04 09:15:49 +04:00
|
|
|
if (!ret)
|
2019-01-18 07:19:43 +03:00
|
|
|
return FOUND;
|
2006-09-21 03:11:08 +04:00
|
|
|
|
|
|
|
/* It could be describe output that is "SOMETHING-gXXXX" */
|
2019-04-16 12:33:32 +03:00
|
|
|
ret = get_describe_name(r, name, len, oid);
|
2006-09-21 03:11:08 +04:00
|
|
|
if (!ret)
|
2019-01-18 07:19:43 +03:00
|
|
|
return FOUND;
|
2006-09-21 03:11:08 +04:00
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
return get_short_oid(r, name, len, oid, lookup_flags);
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
|
|
|
|
2010-08-03 01:37:06 +04:00
|
|
|
/*
|
|
|
|
* This interprets names like ':/Initial revision of "git"' by searching
|
|
|
|
* through history and returning the first commit whose message starts
|
2010-08-13 05:32:49 +04:00
|
|
|
* the given regular expression.
|
2010-08-03 01:37:06 +04:00
|
|
|
*
|
object name: introduce '^{/!-<negative pattern>}' notation
To name a commit, you can now use the :/!-<negative pattern> regex
style, and consequentially, say
$ git rev-parse HEAD^{/!-foo}
and it will return the hash of the first commit reachable from HEAD,
whose commit message does not contain "foo". This is the opposite of the
existing <rev>^{/<pattern>} syntax.
The specific use-case this is intended for is to perform an operation,
excluding the most-recent commits containing a particular marker. For
example, if you tend to make "work in progress" commits, with messages
beginning with "WIP", you work, then it could be useful to diff against
"the most recent commit which was not a WIP commit". That sort of thing
now possible, via commands such as:
$ git diff @^{/!-^WIP}
The leader '/!-', rather than simply '/!', to denote a negative match,
is chosen to leave room for additional modifiers in the future.
Signed-off-by: Will Palmer <wmpalmer@gmail.com>
Signed-off-by: Stephen P. Smith <ischis2@cox.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-31 03:06:01 +03:00
|
|
|
* For negative-matching, prefix the pattern-part with '!-', like: ':/!-WIP'.
|
|
|
|
*
|
|
|
|
* For a literal '!' character at the beginning of a pattern, you have to repeat
|
|
|
|
* that, like: ':/!!foo'
|
|
|
|
*
|
|
|
|
* For future extension, all other sequences beginning with ':/!' are reserved.
|
2010-08-03 01:37:06 +04:00
|
|
|
*/
|
2014-03-25 17:23:26 +04:00
|
|
|
|
|
|
|
/* Remember to update object flag allocation in object.h */
|
2010-08-03 01:37:06 +04:00
|
|
|
#define ONELINE_SEEN (1u<<20)
|
|
|
|
|
2019-04-16 12:33:33 +03:00
|
|
|
struct handle_one_ref_cb {
|
|
|
|
struct repository *repo;
|
|
|
|
struct commit_list **list;
|
|
|
|
};
|
|
|
|
|
2015-05-25 21:39:05 +03:00
|
|
|
static int handle_one_ref(const char *path, const struct object_id *oid,
|
|
|
|
int flag, void *cb_data)
|
2007-02-24 05:08:20 +03:00
|
|
|
{
|
2019-04-16 12:33:33 +03:00
|
|
|
struct handle_one_ref_cb *cb = cb_data;
|
|
|
|
struct commit_list **list = cb->list;
|
|
|
|
struct object *object = parse_object(cb->repo, oid);
|
2007-02-24 05:08:20 +03:00
|
|
|
if (!object)
|
|
|
|
return 0;
|
2008-02-18 10:31:54 +03:00
|
|
|
if (object->type == OBJ_TAG) {
|
2019-04-16 12:33:33 +03:00
|
|
|
object = deref_tag(cb->repo, object, path,
|
2018-06-29 04:22:05 +03:00
|
|
|
strlen(path));
|
2008-02-18 10:31:54 +03:00
|
|
|
if (!object)
|
|
|
|
return 0;
|
|
|
|
}
|
2007-02-24 05:08:20 +03:00
|
|
|
if (object->type != OBJ_COMMIT)
|
|
|
|
return 0;
|
2014-08-21 22:30:29 +04:00
|
|
|
commit_list_insert((struct commit *)object, list);
|
2007-02-24 05:08:20 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:29 +03:00
|
|
|
static int get_oid_oneline(struct repository *r,
|
|
|
|
const char *prefix, struct object_id *oid,
|
|
|
|
struct commit_list *list)
|
2007-02-24 05:08:20 +03:00
|
|
|
{
|
2010-12-13 06:01:14 +03:00
|
|
|
struct commit_list *backup = NULL, *l;
|
2010-12-13 09:19:00 +03:00
|
|
|
int found = 0;
|
object name: introduce '^{/!-<negative pattern>}' notation
To name a commit, you can now use the :/!-<negative pattern> regex
style, and consequentially, say
$ git rev-parse HEAD^{/!-foo}
and it will return the hash of the first commit reachable from HEAD,
whose commit message does not contain "foo". This is the opposite of the
existing <rev>^{/<pattern>} syntax.
The specific use-case this is intended for is to perform an operation,
excluding the most-recent commits containing a particular marker. For
example, if you tend to make "work in progress" commits, with messages
beginning with "WIP", you work, then it could be useful to diff against
"the most recent commit which was not a WIP commit". That sort of thing
now possible, via commands such as:
$ git diff @^{/!-^WIP}
The leader '/!-', rather than simply '/!', to denote a negative match,
is chosen to leave room for additional modifiers in the future.
Signed-off-by: Will Palmer <wmpalmer@gmail.com>
Signed-off-by: Stephen P. Smith <ischis2@cox.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-31 03:06:01 +03:00
|
|
|
int negative = 0;
|
2010-04-23 19:20:20 +04:00
|
|
|
regex_t regex;
|
2007-02-24 05:08:20 +03:00
|
|
|
|
|
|
|
if (prefix[0] == '!') {
|
|
|
|
prefix++;
|
object name: introduce '^{/!-<negative pattern>}' notation
To name a commit, you can now use the :/!-<negative pattern> regex
style, and consequentially, say
$ git rev-parse HEAD^{/!-foo}
and it will return the hash of the first commit reachable from HEAD,
whose commit message does not contain "foo". This is the opposite of the
existing <rev>^{/<pattern>} syntax.
The specific use-case this is intended for is to perform an operation,
excluding the most-recent commits containing a particular marker. For
example, if you tend to make "work in progress" commits, with messages
beginning with "WIP", you work, then it could be useful to diff against
"the most recent commit which was not a WIP commit". That sort of thing
now possible, via commands such as:
$ git diff @^{/!-^WIP}
The leader '/!-', rather than simply '/!', to denote a negative match,
is chosen to leave room for additional modifiers in the future.
Signed-off-by: Will Palmer <wmpalmer@gmail.com>
Signed-off-by: Stephen P. Smith <ischis2@cox.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-31 03:06:01 +03:00
|
|
|
|
|
|
|
if (prefix[0] == '-') {
|
|
|
|
prefix++;
|
|
|
|
negative = 1;
|
|
|
|
} else if (prefix[0] != '!') {
|
2016-02-25 00:25:52 +03:00
|
|
|
return -1;
|
object name: introduce '^{/!-<negative pattern>}' notation
To name a commit, you can now use the :/!-<negative pattern> regex
style, and consequentially, say
$ git rev-parse HEAD^{/!-foo}
and it will return the hash of the first commit reachable from HEAD,
whose commit message does not contain "foo". This is the opposite of the
existing <rev>^{/<pattern>} syntax.
The specific use-case this is intended for is to perform an operation,
excluding the most-recent commits containing a particular marker. For
example, if you tend to make "work in progress" commits, with messages
beginning with "WIP", you work, then it could be useful to diff against
"the most recent commit which was not a WIP commit". That sort of thing
now possible, via commands such as:
$ git diff @^{/!-^WIP}
The leader '/!-', rather than simply '/!', to denote a negative match,
is chosen to leave room for additional modifiers in the future.
Signed-off-by: Will Palmer <wmpalmer@gmail.com>
Signed-off-by: Stephen P. Smith <ischis2@cox.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-31 03:06:01 +03:00
|
|
|
}
|
2007-02-24 05:08:20 +03:00
|
|
|
}
|
2010-04-23 19:20:20 +04:00
|
|
|
|
|
|
|
if (regcomp(®ex, prefix, REG_EXTENDED))
|
2016-02-11 00:19:25 +03:00
|
|
|
return -1;
|
2010-04-23 19:20:20 +04:00
|
|
|
|
2010-12-13 06:01:14 +03:00
|
|
|
for (l = list; l; l = l->next) {
|
|
|
|
l->item->object.flags |= ONELINE_SEEN;
|
2007-02-24 05:08:20 +03:00
|
|
|
commit_list_insert(l->item, &backup);
|
2010-12-13 06:01:14 +03:00
|
|
|
}
|
2007-03-11 21:49:08 +03:00
|
|
|
while (list) {
|
2014-06-11 01:41:02 +04:00
|
|
|
const char *p, *buf;
|
2007-03-12 21:30:38 +03:00
|
|
|
struct commit *commit;
|
2010-12-13 09:19:00 +03:00
|
|
|
int matches;
|
2007-03-11 21:49:08 +03:00
|
|
|
|
|
|
|
commit = pop_most_recent_commit(&list, ONELINE_SEEN);
|
2019-04-16 12:33:29 +03:00
|
|
|
if (!parse_object(r, &commit->object.oid))
|
2008-02-18 23:47:53 +03:00
|
|
|
continue;
|
2014-06-11 01:44:13 +04:00
|
|
|
buf = get_commit_buffer(commit, NULL);
|
2014-06-11 01:41:02 +04:00
|
|
|
p = strstr(buf, "\n\n");
|
object name: introduce '^{/!-<negative pattern>}' notation
To name a commit, you can now use the :/!-<negative pattern> regex
style, and consequentially, say
$ git rev-parse HEAD^{/!-foo}
and it will return the hash of the first commit reachable from HEAD,
whose commit message does not contain "foo". This is the opposite of the
existing <rev>^{/<pattern>} syntax.
The specific use-case this is intended for is to perform an operation,
excluding the most-recent commits containing a particular marker. For
example, if you tend to make "work in progress" commits, with messages
beginning with "WIP", you work, then it could be useful to diff against
"the most recent commit which was not a WIP commit". That sort of thing
now possible, via commands such as:
$ git diff @^{/!-^WIP}
The leader '/!-', rather than simply '/!', to denote a negative match,
is chosen to leave room for additional modifiers in the future.
Signed-off-by: Will Palmer <wmpalmer@gmail.com>
Signed-off-by: Stephen P. Smith <ischis2@cox.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-31 03:06:01 +03:00
|
|
|
matches = negative ^ (p && !regexec(®ex, p + 2, 0, NULL, 0));
|
2014-06-11 01:41:02 +04:00
|
|
|
unuse_commit_buffer(commit, buf);
|
2010-12-13 09:19:00 +03:00
|
|
|
|
|
|
|
if (matches) {
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oidcpy(oid, &commit->object.oid);
|
2010-12-13 09:19:00 +03:00
|
|
|
found = 1;
|
2007-02-24 05:08:20 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-04-23 19:20:20 +04:00
|
|
|
regfree(®ex);
|
2007-02-24 05:08:20 +03:00
|
|
|
free_commit_list(list);
|
|
|
|
for (l = backup; l; l = l->next)
|
|
|
|
clear_commit_marks(l->item, ONELINE_SEEN);
|
2010-12-13 09:19:00 +03:00
|
|
|
free_commit_list(backup);
|
|
|
|
return found ? 0 : -1;
|
2007-02-24 05:08:20 +03:00
|
|
|
}
|
|
|
|
|
2009-01-17 19:09:53 +03:00
|
|
|
struct grab_nth_branch_switch_cbdata {
|
2013-03-09 01:27:37 +04:00
|
|
|
int remaining;
|
2019-09-18 19:35:38 +03:00
|
|
|
struct strbuf *sb;
|
2009-01-17 19:09:53 +03:00
|
|
|
};
|
|
|
|
|
2017-02-22 02:47:32 +03:00
|
|
|
static int grab_nth_branch_switch(struct object_id *ooid, struct object_id *noid,
|
2017-04-26 22:29:31 +03:00
|
|
|
const char *email, timestamp_t timestamp, int tz,
|
2009-01-17 19:09:53 +03:00
|
|
|
const char *message, void *cb_data)
|
|
|
|
{
|
|
|
|
struct grab_nth_branch_switch_cbdata *cb = cb_data;
|
2009-01-17 19:09:54 +03:00
|
|
|
const char *match = NULL, *target = NULL;
|
|
|
|
size_t len;
|
|
|
|
|
2014-06-18 23:48:29 +04:00
|
|
|
if (skip_prefix(message, "checkout: moving from ", &match))
|
2009-01-21 11:37:38 +03:00
|
|
|
target = strstr(match, " to ");
|
2009-01-17 19:09:53 +03:00
|
|
|
|
2009-01-20 03:44:08 +03:00
|
|
|
if (!match || !target)
|
2009-01-17 19:09:53 +03:00
|
|
|
return 0;
|
2013-03-09 01:27:37 +04:00
|
|
|
if (--(cb->remaining) == 0) {
|
|
|
|
len = target - match;
|
2019-09-18 19:35:38 +03:00
|
|
|
strbuf_reset(cb->sb);
|
|
|
|
strbuf_add(cb->sb, match, len);
|
2013-03-09 01:27:37 +04:00
|
|
|
return 1; /* we are done */
|
|
|
|
}
|
2009-01-17 19:09:53 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-01-20 10:17:11 +03:00
|
|
|
* Parse @{-N} syntax, return the number of characters parsed
|
|
|
|
* if successful; otherwise signal an error with negative value.
|
2009-01-17 19:09:53 +03:00
|
|
|
*/
|
2019-04-16 12:33:26 +03:00
|
|
|
static int interpret_nth_prior_checkout(struct repository *r,
|
|
|
|
const char *name, int namelen,
|
interpret_branch_name: always respect "namelen" parameter
interpret_branch_name gets passed a "name" buffer to parse,
along with a "namelen" parameter representing its length. If
"namelen" is zero, we fallback to the NUL-terminated
string-length of "name".
However, it does not necessarily follow that if we have
gotten a non-zero "namelen", it is the NUL-terminated
string-length of "name". E.g., when get_sha1() is parsing
"foo:bar", we will be asked to operate only on the first
three characters.
Yet in interpret_branch_name and its helpers, we use string
functions like strchr() to operate on "name", looking past
the length we were given. This can result in us mis-parsing
object names. We should instead be limiting our search to
"namelen" bytes.
There are three distinct types of object names this patch
addresses:
- The intrepret_empty_at helper uses strchr to find the
next @-expression after our potential empty-at. In an
expression like "@:foo@bar", it erroneously thinks that
the second "@" is relevant, even if we were asked only
to look at the first character. This case is easy to
trigger (and we test it in this patch).
- When finding the initial @-mark for @{upstream}, we use
strchr. This means we might treat "foo:@{upstream}" as
the upstream for "foo:", even though we were asked only
to look at "foo". We cannot test this one in practice,
because it is masked by another bug (which is fixed in
the next patch).
- The interpret_nth_prior_checkout helper did not receive
the name length at all. This turns out not to be a
problem in practice, though, because its parsing is so
limited: it always starts from the far-left of the
string, and will not tolerate a colon (which is
currently the only way to get a smaller-than-strlen
"namelen"). However, it's still worth fixing to make the
code more obviously correct, and to future-proof us
against callers with more exotic buffers.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:31:57 +04:00
|
|
|
struct strbuf *buf)
|
2009-01-17 19:09:53 +03:00
|
|
|
{
|
2009-01-19 11:04:25 +03:00
|
|
|
long nth;
|
2013-03-09 01:27:37 +04:00
|
|
|
int retval;
|
2009-01-17 19:09:53 +03:00
|
|
|
struct grab_nth_branch_switch_cbdata cb;
|
2009-01-17 19:09:54 +03:00
|
|
|
const char *brace;
|
|
|
|
char *num_end;
|
2009-01-17 19:09:53 +03:00
|
|
|
|
interpret_branch_name: always respect "namelen" parameter
interpret_branch_name gets passed a "name" buffer to parse,
along with a "namelen" parameter representing its length. If
"namelen" is zero, we fallback to the NUL-terminated
string-length of "name".
However, it does not necessarily follow that if we have
gotten a non-zero "namelen", it is the NUL-terminated
string-length of "name". E.g., when get_sha1() is parsing
"foo:bar", we will be asked to operate only on the first
three characters.
Yet in interpret_branch_name and its helpers, we use string
functions like strchr() to operate on "name", looking past
the length we were given. This can result in us mis-parsing
object names. We should instead be limiting our search to
"namelen" bytes.
There are three distinct types of object names this patch
addresses:
- The intrepret_empty_at helper uses strchr to find the
next @-expression after our potential empty-at. In an
expression like "@:foo@bar", it erroneously thinks that
the second "@" is relevant, even if we were asked only
to look at the first character. This case is easy to
trigger (and we test it in this patch).
- When finding the initial @-mark for @{upstream}, we use
strchr. This means we might treat "foo:@{upstream}" as
the upstream for "foo:", even though we were asked only
to look at "foo". We cannot test this one in practice,
because it is masked by another bug (which is fixed in
the next patch).
- The interpret_nth_prior_checkout helper did not receive
the name length at all. This turns out not to be a
problem in practice, though, because its parsing is so
limited: it always starts from the far-left of the
string, and will not tolerate a colon (which is
currently the only way to get a smaller-than-strlen
"namelen"). However, it's still worth fixing to make the
code more obviously correct, and to future-proof us
against callers with more exotic buffers.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:31:57 +04:00
|
|
|
if (namelen < 4)
|
|
|
|
return -1;
|
2009-01-17 19:09:53 +03:00
|
|
|
if (name[0] != '@' || name[1] != '{' || name[2] != '-')
|
|
|
|
return -1;
|
interpret_branch_name: always respect "namelen" parameter
interpret_branch_name gets passed a "name" buffer to parse,
along with a "namelen" parameter representing its length. If
"namelen" is zero, we fallback to the NUL-terminated
string-length of "name".
However, it does not necessarily follow that if we have
gotten a non-zero "namelen", it is the NUL-terminated
string-length of "name". E.g., when get_sha1() is parsing
"foo:bar", we will be asked to operate only on the first
three characters.
Yet in interpret_branch_name and its helpers, we use string
functions like strchr() to operate on "name", looking past
the length we were given. This can result in us mis-parsing
object names. We should instead be limiting our search to
"namelen" bytes.
There are three distinct types of object names this patch
addresses:
- The intrepret_empty_at helper uses strchr to find the
next @-expression after our potential empty-at. In an
expression like "@:foo@bar", it erroneously thinks that
the second "@" is relevant, even if we were asked only
to look at the first character. This case is easy to
trigger (and we test it in this patch).
- When finding the initial @-mark for @{upstream}, we use
strchr. This means we might treat "foo:@{upstream}" as
the upstream for "foo:", even though we were asked only
to look at "foo". We cannot test this one in practice,
because it is masked by another bug (which is fixed in
the next patch).
- The interpret_nth_prior_checkout helper did not receive
the name length at all. This turns out not to be a
problem in practice, though, because its parsing is so
limited: it always starts from the far-left of the
string, and will not tolerate a colon (which is
currently the only way to get a smaller-than-strlen
"namelen"). However, it's still worth fixing to make the
code more obviously correct, and to future-proof us
against callers with more exotic buffers.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:31:57 +04:00
|
|
|
brace = memchr(name, '}', namelen);
|
2009-01-17 19:09:54 +03:00
|
|
|
if (!brace)
|
|
|
|
return -1;
|
2013-03-09 01:27:37 +04:00
|
|
|
nth = strtol(name + 3, &num_end, 10);
|
2009-01-17 19:09:54 +03:00
|
|
|
if (num_end != brace)
|
2009-01-17 19:09:53 +03:00
|
|
|
return -1;
|
2009-01-19 11:04:25 +03:00
|
|
|
if (nth <= 0)
|
|
|
|
return -1;
|
2013-03-09 01:27:37 +04:00
|
|
|
cb.remaining = nth;
|
2019-09-18 19:35:38 +03:00
|
|
|
cb.sb = buf;
|
2013-03-09 01:27:37 +04:00
|
|
|
|
2019-04-16 12:33:26 +03:00
|
|
|
retval = refs_for_each_reflog_ent_reverse(get_main_ref_store(r),
|
|
|
|
"HEAD", grab_nth_branch_switch, &cb);
|
|
|
|
if (0 < retval) {
|
2013-03-09 01:27:37 +04:00
|
|
|
retval = brace - name + 1;
|
2019-04-16 12:33:26 +03:00
|
|
|
} else
|
|
|
|
retval = 0;
|
2009-01-17 19:09:54 +03:00
|
|
|
|
2009-01-20 08:58:31 +03:00
|
|
|
return retval;
|
2009-01-17 19:09:53 +03:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:41 +03:00
|
|
|
int repo_get_oid_mb(struct repository *r,
|
|
|
|
const char *name,
|
|
|
|
struct object_id *oid)
|
2009-10-18 23:34:56 +04:00
|
|
|
{
|
|
|
|
struct commit *one, *two;
|
|
|
|
struct commit_list *mbs;
|
2016-09-05 23:08:07 +03:00
|
|
|
struct object_id oid_tmp;
|
2009-10-18 23:34:56 +04:00
|
|
|
const char *dots;
|
|
|
|
int st;
|
|
|
|
|
|
|
|
dots = strstr(name, "...");
|
|
|
|
if (!dots)
|
2019-04-16 12:33:41 +03:00
|
|
|
return repo_get_oid(r, name, oid);
|
2009-10-18 23:34:56 +04:00
|
|
|
if (dots == name)
|
2019-04-16 12:33:41 +03:00
|
|
|
st = repo_get_oid(r, "HEAD", &oid_tmp);
|
2009-10-18 23:34:56 +04:00
|
|
|
else {
|
|
|
|
struct strbuf sb;
|
|
|
|
strbuf_init(&sb, dots - name);
|
|
|
|
strbuf_add(&sb, name, dots - name);
|
2019-04-16 12:33:41 +03:00
|
|
|
st = repo_get_oid_committish(r, sb.buf, &oid_tmp);
|
2009-10-18 23:34:56 +04:00
|
|
|
strbuf_release(&sb);
|
|
|
|
}
|
|
|
|
if (st)
|
|
|
|
return st;
|
2019-04-16 12:33:41 +03:00
|
|
|
one = lookup_commit_reference_gently(r, &oid_tmp, 0);
|
2009-10-18 23:34:56 +04:00
|
|
|
if (!one)
|
|
|
|
return -1;
|
|
|
|
|
2019-04-16 12:33:41 +03:00
|
|
|
if (repo_get_oid_committish(r, dots[3] ? (dots + 3) : "HEAD", &oid_tmp))
|
2009-10-18 23:34:56 +04:00
|
|
|
return -1;
|
2019-04-16 12:33:41 +03:00
|
|
|
two = lookup_commit_reference_gently(r, &oid_tmp, 0);
|
2009-10-18 23:34:56 +04:00
|
|
|
if (!two)
|
|
|
|
return -1;
|
2019-06-27 12:28:52 +03:00
|
|
|
mbs = repo_get_merge_bases(r, one, two);
|
2009-10-18 23:34:56 +04:00
|
|
|
if (!mbs || mbs->next)
|
|
|
|
st = -1;
|
|
|
|
else {
|
|
|
|
st = 0;
|
2016-09-05 23:08:07 +03:00
|
|
|
oidcpy(oid, &mbs->item->object.oid);
|
2009-10-18 23:34:56 +04:00
|
|
|
}
|
|
|
|
free_commit_list(mbs);
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
Add new @ shortcut for HEAD
Typing 'HEAD' is tedious, especially when we can use '@' instead.
The reason for choosing '@' is that it follows naturally from the
ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no
operation, and when we don't have those, it makes sens to assume
'HEAD'.
So now we can use 'git show @~1', and all that goody goodness.
Until now '@' was a valid name, but it conflicts with this idea, so
let's make it invalid. Probably very few people, if any, used this name.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-09-02 10:34:30 +04:00
|
|
|
/* parse @something syntax, when 'something' is not {.*} */
|
|
|
|
static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf)
|
|
|
|
{
|
|
|
|
const char *next;
|
|
|
|
|
|
|
|
if (len || name[1] == '{')
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* make sure it's a single @, or @@{.*}, not @foo */
|
interpret_branch_name: always respect "namelen" parameter
interpret_branch_name gets passed a "name" buffer to parse,
along with a "namelen" parameter representing its length. If
"namelen" is zero, we fallback to the NUL-terminated
string-length of "name".
However, it does not necessarily follow that if we have
gotten a non-zero "namelen", it is the NUL-terminated
string-length of "name". E.g., when get_sha1() is parsing
"foo:bar", we will be asked to operate only on the first
three characters.
Yet in interpret_branch_name and its helpers, we use string
functions like strchr() to operate on "name", looking past
the length we were given. This can result in us mis-parsing
object names. We should instead be limiting our search to
"namelen" bytes.
There are three distinct types of object names this patch
addresses:
- The intrepret_empty_at helper uses strchr to find the
next @-expression after our potential empty-at. In an
expression like "@:foo@bar", it erroneously thinks that
the second "@" is relevant, even if we were asked only
to look at the first character. This case is easy to
trigger (and we test it in this patch).
- When finding the initial @-mark for @{upstream}, we use
strchr. This means we might treat "foo:@{upstream}" as
the upstream for "foo:", even though we were asked only
to look at "foo". We cannot test this one in practice,
because it is masked by another bug (which is fixed in
the next patch).
- The interpret_nth_prior_checkout helper did not receive
the name length at all. This turns out not to be a
problem in practice, though, because its parsing is so
limited: it always starts from the far-left of the
string, and will not tolerate a colon (which is
currently the only way to get a smaller-than-strlen
"namelen"). However, it's still worth fixing to make the
code more obviously correct, and to future-proof us
against callers with more exotic buffers.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:31:57 +04:00
|
|
|
next = memchr(name + len + 1, '@', namelen - len - 1);
|
Add new @ shortcut for HEAD
Typing 'HEAD' is tedious, especially when we can use '@' instead.
The reason for choosing '@' is that it follows naturally from the
ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no
operation, and when we don't have those, it makes sens to assume
'HEAD'.
So now we can use 'git show @~1', and all that goody goodness.
Until now '@' was a valid name, but it conflicts with this idea, so
let's make it invalid. Probably very few people, if any, used this name.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-09-02 10:34:30 +04:00
|
|
|
if (next && next[1] != '{')
|
|
|
|
return -1;
|
|
|
|
if (!next)
|
|
|
|
next = name + namelen;
|
|
|
|
if (next != name + 1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
strbuf_reset(buf);
|
|
|
|
strbuf_add(buf, "HEAD", 4);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:28 +03:00
|
|
|
static int reinterpret(struct repository *r,
|
|
|
|
const char *name, int namelen, int len,
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
struct strbuf *buf, unsigned allowed)
|
2013-05-08 02:04:30 +04:00
|
|
|
{
|
|
|
|
/* we have extra data, which might need further processing */
|
|
|
|
struct strbuf tmp = STRBUF_INIT;
|
|
|
|
int used = buf->len;
|
|
|
|
int ret;
|
2020-09-02 01:28:07 +03:00
|
|
|
struct interpret_branch_name_options options = {
|
|
|
|
.allowed = allowed
|
|
|
|
};
|
2013-05-08 02:04:30 +04:00
|
|
|
|
|
|
|
strbuf_add(buf, name + len, namelen - len);
|
2020-09-02 01:28:07 +03:00
|
|
|
ret = repo_interpret_branch_name(r, buf->buf, buf->len, &tmp, &options);
|
2013-05-08 02:04:30 +04:00
|
|
|
/* that data was not interpreted, remove our cruft */
|
|
|
|
if (ret < 0) {
|
|
|
|
strbuf_setlen(buf, used);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
strbuf_reset(buf);
|
|
|
|
strbuf_addbuf(buf, &tmp);
|
|
|
|
strbuf_release(&tmp);
|
|
|
|
/* tweak for size of {-N} versus expanded ref name */
|
|
|
|
return ret - used + len;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:27 +03:00
|
|
|
static void set_shortened_ref(struct repository *r, struct strbuf *buf, const char *ref)
|
2014-01-15 12:26:33 +04:00
|
|
|
{
|
2019-04-16 12:33:27 +03:00
|
|
|
char *s = refs_shorten_unambiguous_ref(get_main_ref_store(r), ref, 0);
|
2014-01-15 12:26:33 +04:00
|
|
|
strbuf_reset(buf);
|
|
|
|
strbuf_addstr(buf, s);
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
static int branch_interpret_allowed(const char *refname, unsigned allowed)
|
|
|
|
{
|
|
|
|
if (!allowed)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if ((allowed & INTERPRET_BRANCH_LOCAL) &&
|
|
|
|
starts_with(refname, "refs/heads/"))
|
|
|
|
return 1;
|
|
|
|
if ((allowed & INTERPRET_BRANCH_REMOTE) &&
|
|
|
|
starts_with(refname, "refs/remotes/"))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:27 +03:00
|
|
|
static int interpret_branch_mark(struct repository *r,
|
|
|
|
const char *name, int namelen,
|
2015-05-21 07:45:43 +03:00
|
|
|
int at, struct strbuf *buf,
|
|
|
|
int (*get_mark)(const char *, int),
|
|
|
|
const char *(*get_data)(struct branch *,
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
struct strbuf *),
|
2020-09-02 01:28:07 +03:00
|
|
|
const struct interpret_branch_name_options *options)
|
2014-01-15 12:26:33 +04:00
|
|
|
{
|
|
|
|
int len;
|
2015-05-21 07:45:43 +03:00
|
|
|
struct branch *branch;
|
|
|
|
struct strbuf err = STRBUF_INIT;
|
|
|
|
const char *value;
|
2014-01-15 12:26:33 +04:00
|
|
|
|
2015-05-21 07:45:43 +03:00
|
|
|
len = get_mark(name + at, namelen - at);
|
2014-01-15 12:26:33 +04:00
|
|
|
if (!len)
|
|
|
|
return -1;
|
|
|
|
|
interpret_branch_name: avoid @{upstream} past colon
get_sha1() cannot currently parse a valid object name like
"HEAD:@{upstream}" (assuming that such an oddly named file
exists in the HEAD commit). It takes two passes to parse the
string:
1. It first considers the whole thing as a ref, which
results in looking for the upstream of "HEAD:".
2. It finds the colon, parses "HEAD" as a tree-ish, and then
finds the path "@{upstream}" in the tree.
For a path that looks like a normal reflog (e.g.,
"HEAD:@{yesterday}"), the first pass is a no-op. We try to
dwim_ref("HEAD:"), that returns zero refs, and we proceed
with colon-parsing.
For "HEAD:@{upstream}", though, the first pass ends up in
interpret_upstream_mark, which tries to find the branch
"HEAD:". When it sees that the branch does not exist, it
actually dies rather than returning an error to the caller.
As a result, we never make it to the second pass.
One obvious way of fixing this would be to teach
interpret_upstream_mark to simply report "no, this isn't an
upstream" in such a case. However, that would make the
error-reporting for legitimate upstream cases significantly
worse. Something like "bogus@{upstream}" would simply report
"unknown revision: bogus@{upstream}", while the current code
diagnoses a wide variety of possible misconfigurations (no
such branch, branch exists but does not have upstream, etc).
However, we can take advantage of the fact that a branch
name cannot contain a colon. Therefore even if we find an
upstream mark, any prefix with a colon must mean that
the upstream mark we found is actually a pathname, and
should be disregarded completely. This patch implements that
logic.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:37:23 +04:00
|
|
|
if (memchr(name, ':', at))
|
|
|
|
return -1;
|
|
|
|
|
2015-05-21 07:45:43 +03:00
|
|
|
if (at) {
|
|
|
|
char *name_str = xmemdupz(name, at);
|
|
|
|
branch = branch_get(name_str);
|
|
|
|
free(name_str);
|
|
|
|
} else
|
|
|
|
branch = branch_get(NULL);
|
|
|
|
|
|
|
|
value = get_data(branch, &err);
|
2020-09-02 01:28:09 +03:00
|
|
|
if (!value) {
|
|
|
|
if (options->nonfatal_dangling_mark) {
|
|
|
|
strbuf_release(&err);
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
die("%s", err.buf);
|
|
|
|
}
|
|
|
|
}
|
2015-05-21 07:45:43 +03:00
|
|
|
|
2020-09-02 01:28:07 +03:00
|
|
|
if (!branch_interpret_allowed(value, options->allowed))
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
return -1;
|
|
|
|
|
2019-04-16 12:33:27 +03:00
|
|
|
set_shortened_ref(r, buf, value);
|
2014-01-15 12:26:33 +04:00
|
|
|
return len + at;
|
|
|
|
}
|
|
|
|
|
2019-04-06 14:34:26 +03:00
|
|
|
int repo_interpret_branch_name(struct repository *r,
|
|
|
|
const char *name, int namelen,
|
|
|
|
struct strbuf *buf,
|
2020-09-02 01:28:07 +03:00
|
|
|
const struct interpret_branch_name_options *options)
|
2010-01-20 10:17:11 +03:00
|
|
|
{
|
2014-01-15 12:27:32 +04:00
|
|
|
char *at;
|
interpret_branch_name: find all possible @-marks
When we parse a string like "foo@{upstream}", we look for
the first "@"-sign, and check to see if it is an upstream
mark. However, since branch names can contain an @, we may
also see "@foo@{upstream}". In this case, we check only the
first @, and ignore the second. As a result, we do not find
the upstream.
We can solve this by iterating through all @-marks in the
string, and seeing if any is a legitimate upstream or
empty-at mark.
Another strategy would be to parse from the right-hand side
of the string. However, that does not work for the
"empty_at" case, which allows "@@{upstream}". We need to
find the left-most one in this case (and we then recurse as
"HEAD@{upstream}").
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:40:46 +04:00
|
|
|
const char *start;
|
2017-02-27 12:25:40 +03:00
|
|
|
int len;
|
2010-01-20 10:17:11 +03:00
|
|
|
|
2013-09-02 10:34:29 +04:00
|
|
|
if (!namelen)
|
|
|
|
namelen = strlen(name);
|
|
|
|
|
2020-09-02 01:28:07 +03:00
|
|
|
if (!options->allowed || (options->allowed & INTERPRET_BRANCH_LOCAL)) {
|
2019-04-16 12:33:28 +03:00
|
|
|
len = interpret_nth_prior_checkout(r, name, namelen, buf);
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
if (!len) {
|
|
|
|
return len; /* syntax Ok, not enough switches */
|
|
|
|
} else if (len > 0) {
|
|
|
|
if (len == namelen)
|
|
|
|
return len; /* consumed all */
|
|
|
|
else
|
2020-09-02 01:28:07 +03:00
|
|
|
return reinterpret(r, name, namelen, len, buf,
|
|
|
|
options->allowed);
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
}
|
2010-01-28 12:52:22 +03:00
|
|
|
}
|
|
|
|
|
interpret_branch_name: find all possible @-marks
When we parse a string like "foo@{upstream}", we look for
the first "@"-sign, and check to see if it is an upstream
mark. However, since branch names can contain an @, we may
also see "@foo@{upstream}". In this case, we check only the
first @, and ignore the second. As a result, we do not find
the upstream.
We can solve this by iterating through all @-marks in the
string, and seeing if any is a legitimate upstream or
empty-at mark.
Another strategy would be to parse from the right-hand side
of the string. However, that does not work for the
"empty_at" case, which allows "@@{upstream}". We need to
find the left-most one in this case (and we then recurse as
"HEAD@{upstream}").
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:40:46 +04:00
|
|
|
for (start = name;
|
|
|
|
(at = memchr(start, '@', namelen - (start - name)));
|
|
|
|
start = at + 1) {
|
Add new @ shortcut for HEAD
Typing 'HEAD' is tedious, especially when we can use '@' instead.
The reason for choosing '@' is that it follows naturally from the
ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no
operation, and when we don't have those, it makes sens to assume
'HEAD'.
So now we can use 'git show @~1', and all that goody goodness.
Until now '@' was a valid name, but it conflicts with this idea, so
let's make it invalid. Probably very few people, if any, used this name.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-09-02 10:34:30 +04:00
|
|
|
|
2020-09-02 01:28:07 +03:00
|
|
|
if (!options->allowed || (options->allowed & INTERPRET_BRANCH_HEAD)) {
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
len = interpret_empty_at(name, namelen, at - name, buf);
|
|
|
|
if (len > 0)
|
2019-04-16 12:33:28 +03:00
|
|
|
return reinterpret(r, name, namelen, len, buf,
|
2020-09-02 01:28:07 +03:00
|
|
|
options->allowed);
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
}
|
Add new @ shortcut for HEAD
Typing 'HEAD' is tedious, especially when we can use '@' instead.
The reason for choosing '@' is that it follows naturally from the
ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no
operation, and when we don't have those, it makes sens to assume
'HEAD'.
So now we can use 'git show @~1', and all that goody goodness.
Until now '@' was a valid name, but it conflicts with this idea, so
let's make it invalid. Probably very few people, if any, used this name.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-09-02 10:34:30 +04:00
|
|
|
|
2019-04-16 12:33:28 +03:00
|
|
|
len = interpret_branch_mark(r, name, namelen, at - name, buf,
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
upstream_mark, branch_get_upstream,
|
2020-09-02 01:28:07 +03:00
|
|
|
options);
|
interpret_branch_name: find all possible @-marks
When we parse a string like "foo@{upstream}", we look for
the first "@"-sign, and check to see if it is an upstream
mark. However, since branch names can contain an @, we may
also see "@foo@{upstream}". In this case, we check only the
first @, and ignore the second. As a result, we do not find
the upstream.
We can solve this by iterating through all @-marks in the
string, and seeing if any is a legitimate upstream or
empty-at mark.
Another strategy would be to parse from the right-hand side
of the string. However, that does not work for the
"empty_at" case, which allows "@@{upstream}". We need to
find the left-most one in this case (and we then recurse as
"HEAD@{upstream}").
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:40:46 +04:00
|
|
|
if (len > 0)
|
|
|
|
return len;
|
sha1_name: implement @{push} shorthand
In a triangular workflow, each branch may have two distinct
points of interest: the @{upstream} that you normally pull
from, and the destination that you normally push to. There
isn't a shorthand for the latter, but it's useful to have.
For instance, you may want to know which commits you haven't
pushed yet:
git log @{push}..
Or as a more complicated example, imagine that you normally
pull changes from origin/master (which you set as your
@{upstream}), and push changes to your own personal fork
(e.g., as myfork/topic). You may push to your fork from
multiple machines, requiring you to integrate the changes
from the push destination, rather than upstream. With this
patch, you can just do:
git rebase @{push}
rather than typing out the full name.
The heavy lifting is all done by branch_get_push; here we
just wire it up to the "@{push}" syntax.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-21 07:45:47 +03:00
|
|
|
|
2019-04-16 12:33:28 +03:00
|
|
|
len = interpret_branch_mark(r, name, namelen, at - name, buf,
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
push_mark, branch_get_push,
|
2020-09-02 01:28:07 +03:00
|
|
|
options);
|
interpret_branch_name: find all possible @-marks
When we parse a string like "foo@{upstream}", we look for
the first "@"-sign, and check to see if it is an upstream
mark. However, since branch names can contain an @, we may
also see "@foo@{upstream}". In this case, we check only the
first @, and ignore the second. As a result, we do not find
the upstream.
We can solve this by iterating through all @-marks in the
string, and seeing if any is a legitimate upstream or
empty-at mark.
Another strategy would be to parse from the right-hand side
of the string. However, that does not work for the
"empty_at" case, which allows "@@{upstream}". We need to
find the left-most one in this case (and we then recurse as
"HEAD@{upstream}").
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-15 12:40:46 +04:00
|
|
|
if (len > 0)
|
|
|
|
return len;
|
2012-04-14 11:54:33 +04:00
|
|
|
}
|
Add new @ shortcut for HEAD
Typing 'HEAD' is tedious, especially when we can use '@' instead.
The reason for choosing '@' is that it follows naturally from the
ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no
operation, and when we don't have those, it makes sens to assume
'HEAD'.
So now we can use 'git show @~1', and all that goody goodness.
Until now '@' was a valid name, but it conflicts with this idea, so
let's make it invalid. Probably very few people, if any, used this name.
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-09-02 10:34:30 +04:00
|
|
|
|
2014-01-15 12:26:33 +04:00
|
|
|
return -1;
|
2010-01-20 10:17:11 +03:00
|
|
|
}
|
|
|
|
|
interpret_branch_name: allow callers to restrict expansions
The interpret_branch_name() function converts names like
@{-1} and @{upstream} into branch names. The expanded ref
names are not fully qualified, and may be outside of the
refs/heads/ namespace (e.g., "@" expands to "HEAD", and
"@{upstream}" is likely to be in "refs/remotes/").
This is OK for callers like dwim_ref() which are primarily
interested in resolving the resulting name, no matter where
it is. But callers like "git branch" treat the result as a
branch name in refs/heads/. When we expand to a ref outside
that namespace, the results are very confusing (e.g., "git
branch @" tries to create refs/heads/HEAD, which is
nonsense).
Callers can't know from the returned string how the
expansion happened (e.g., did the user really ask for a
branch named "HEAD", or did we do a bogus expansion?). One
fix would be to return some out-parameters describing the
types of expansion that occurred. This has the benefit that
the caller can generate precise error messages ("I
understood @{upstream} to mean origin/master, but that is a
remote tracking branch, so you cannot create it as a local
name").
However, out-parameters make the function interface somewhat
cumbersome. Instead, let's do the opposite: let the caller
tell us which elements to expand. That's easier to pass in,
and none of the callers give more precise error messages
than "@{upstream} isn't a valid branch name" anyway (which
should be sufficient).
The strbuf_branchname() function needs a similar parameter,
as most of the callers access interpret_branch_name()
through it.
We can break the callers down into two groups:
1. Callers that are happy with any kind of ref in the
result. We pass "0" here, so they continue to work
without restrictions. This includes merge_name(),
the reflog handling in add_pending_object_with_path(),
and substitute_branch_name(). This last is what powers
dwim_ref().
2. Callers that have funny corner cases (mostly in
git-branch and git-checkout). These need to make use of
the new parameter, but I've left them as "0" in this
patch, and will address them individually in follow-on
patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-02 11:23:01 +03:00
|
|
|
void strbuf_branchname(struct strbuf *sb, const char *name, unsigned allowed)
|
2010-11-06 14:46:52 +03:00
|
|
|
{
|
|
|
|
int len = strlen(name);
|
2020-09-02 01:28:07 +03:00
|
|
|
struct interpret_branch_name_options options = {
|
|
|
|
.allowed = allowed
|
|
|
|
};
|
|
|
|
int used = interpret_branch_name(name, len, sb, &options);
|
2013-05-16 01:32:30 +04:00
|
|
|
|
|
|
|
if (used < 0)
|
|
|
|
used = 0;
|
|
|
|
strbuf_add(sb, name + used, len - used);
|
2010-11-06 14:46:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
|
|
|
|
{
|
check-ref-format --branch: do not expand @{...} outside repository
Running "git check-ref-format --branch @{-1}" from outside any
repository produces
$ git check-ref-format --branch @{-1}
BUG: environment.c:182: git environment hasn't been setup
This is because the expansion of @{-1} must come from the HEAD reflog,
which involves opening the repository. @{u} and @{push} (which are
more unusual because they typically would not expand to a local
branch) trigger the same assertion.
This has been broken since day one. Before v2.13.0-rc0~48^2
(setup_git_env: avoid blind fall-back to ".git", 2016-10-02), the
breakage was more subtle: Git would read reflogs from ".git" within
the current directory even if it was not a valid repository. Usually
that is harmless because Git is not being run from the root directory
of an invalid repository, but in edge cases such accesses can be
confusing or harmful. Since v2.13.0, the problem is easier to
diagnose because Git aborts with a BUG message.
Erroring out is the right behavior: when asked to interpret a branch
name like "@{-1}", there is no reasonable answer in this context.
But we should print a message saying so instead of an assertion failure.
We do not forbid "check-ref-format --branch" from outside a repository
altogether because it is ok for a script to pre-process branch
arguments without @{...} in such a context. For example, with
pre-2.13 Git, a script that does
branch='master'; # default value
parse_options
branch=$(git check-ref-format --branch "$branch")
to normalize an optional branch name provided by the user would work
both inside a repository (where the user could provide '@{-1}') and
outside (where '@{-1}' should not be accepted).
So disable the "expand @{...}" half of the feature when run outside a
repository, but keep the check of the syntax of a proposed branch
name. This way, when run from outside a repository, "git
check-ref-format --branch @{-1}" will gracefully fail:
$ git check-ref-format --branch @{-1}
fatal: '@{-1}' is not a valid branch name
and "git check-ref-format --branch master" will succeed as before:
$ git check-ref-format --branch master
master
restoring the usual pre-2.13 behavior.
[jn: split out from a larger patch; moved conditional to
strbuf_check_branch_ref instead of its caller; fleshed out commit
message; some style tweaks in tests]
Reported-by: Marko Kungla <marko.kungla@gmail.com>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-10-17 10:08:08 +03:00
|
|
|
if (startup_info->have_repository)
|
|
|
|
strbuf_branchname(sb, name, INTERPRET_BRANCH_LOCAL);
|
|
|
|
else
|
|
|
|
strbuf_addstr(sb, name);
|
2017-11-14 14:42:58 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This splice must be done even if we end up rejecting the
|
|
|
|
* name; builtin/branch.c::copy_or_rename_branch() still wants
|
|
|
|
* to see what the name expanded to so that "branch -m" can be
|
|
|
|
* used as a tool to correct earlier mistakes.
|
|
|
|
*/
|
2010-11-06 14:46:52 +03:00
|
|
|
strbuf_splice(sb, 0, 0, "refs/heads/", 11);
|
2017-11-14 14:42:58 +03:00
|
|
|
|
|
|
|
if (*name == '-' ||
|
|
|
|
!strcmp(sb->buf, "refs/heads/HEAD"))
|
|
|
|
return -1;
|
|
|
|
|
2011-09-16 01:10:25 +04:00
|
|
|
return check_refname_format(sb->buf, 0);
|
2010-11-06 14:46:52 +03:00
|
|
|
}
|
|
|
|
|
2005-08-04 09:15:49 +04:00
|
|
|
/*
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
* This is like "get_oid_basic()", except it allows "object ID expressions",
|
2005-08-04 09:15:49 +04:00
|
|
|
* notably "xyz^" for "parent of xyz"
|
|
|
|
*/
|
2019-04-16 12:33:37 +03:00
|
|
|
int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
|
2016-04-18 02:10:36 +03:00
|
|
|
{
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
struct object_context unused;
|
2019-04-16 12:33:37 +03:00
|
|
|
return get_oid_with_context(r, name, 0, oid, &unused);
|
2016-04-18 02:10:36 +03:00
|
|
|
}
|
|
|
|
|
2019-02-26 02:16:05 +03:00
|
|
|
/*
|
|
|
|
* This returns a non-zero value if the string (built using printf
|
|
|
|
* format and the given arguments) is not a valid object.
|
|
|
|
*/
|
|
|
|
int get_oidf(struct object_id *oid, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
int ret;
|
|
|
|
struct strbuf sb = STRBUF_INIT;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
strbuf_vaddf(&sb, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
ret = get_oid(sb.buf, oid);
|
|
|
|
strbuf_release(&sb);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2016-04-18 02:10:36 +03:00
|
|
|
|
2012-07-02 23:04:52 +04:00
|
|
|
/*
|
2013-09-04 23:04:31 +04:00
|
|
|
* Many callers know that the user meant to name a commit-ish by
|
2012-07-02 23:04:52 +04:00
|
|
|
* syntactical positions where the object name appears. Calling this
|
|
|
|
* function allows the machinery to disambiguate shorter-than-unique
|
2013-09-04 23:04:31 +04:00
|
|
|
* abbreviated object names between commit-ish and others.
|
2012-07-02 23:04:52 +04:00
|
|
|
*
|
|
|
|
* Note that this does NOT error out when the named object is not a
|
2013-09-04 23:04:31 +04:00
|
|
|
* commit-ish. It is merely to give a hint to the disambiguation
|
2012-07-02 23:04:52 +04:00
|
|
|
* machinery.
|
|
|
|
*/
|
2019-04-16 12:33:40 +03:00
|
|
|
int repo_get_oid_committish(struct repository *r,
|
|
|
|
const char *name,
|
|
|
|
struct object_id *oid)
|
2012-07-02 23:04:52 +04:00
|
|
|
{
|
|
|
|
struct object_context unused;
|
2019-04-16 12:33:40 +03:00
|
|
|
return get_oid_with_context(r, name, GET_OID_COMMITTISH,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oid, &unused);
|
2012-07-02 23:04:52 +04:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:40 +03:00
|
|
|
int repo_get_oid_treeish(struct repository *r,
|
|
|
|
const char *name,
|
|
|
|
struct object_id *oid)
|
2012-07-03 10:35:05 +04:00
|
|
|
{
|
|
|
|
struct object_context unused;
|
2019-04-16 12:33:40 +03:00
|
|
|
return get_oid_with_context(r, name, GET_OID_TREEISH,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oid, &unused);
|
2012-07-03 10:35:05 +04:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:40 +03:00
|
|
|
int repo_get_oid_commit(struct repository *r,
|
|
|
|
const char *name,
|
|
|
|
struct object_id *oid)
|
2012-07-03 10:35:05 +04:00
|
|
|
{
|
|
|
|
struct object_context unused;
|
2019-04-16 12:33:40 +03:00
|
|
|
return get_oid_with_context(r, name, GET_OID_COMMIT,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oid, &unused);
|
2012-07-03 10:35:05 +04:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:40 +03:00
|
|
|
int repo_get_oid_tree(struct repository *r,
|
|
|
|
const char *name,
|
|
|
|
struct object_id *oid)
|
2012-07-03 10:35:05 +04:00
|
|
|
{
|
|
|
|
struct object_context unused;
|
2019-04-16 12:33:40 +03:00
|
|
|
return get_oid_with_context(r, name, GET_OID_TREE,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oid, &unused);
|
2012-07-03 10:35:05 +04:00
|
|
|
}
|
|
|
|
|
2019-04-16 12:33:40 +03:00
|
|
|
int repo_get_oid_blob(struct repository *r,
|
|
|
|
const char *name,
|
|
|
|
struct object_id *oid)
|
2012-07-03 10:35:05 +04:00
|
|
|
{
|
|
|
|
struct object_context unused;
|
2019-04-16 12:33:40 +03:00
|
|
|
return get_oid_with_context(r, name, GET_OID_BLOB,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oid, &unused);
|
2007-04-24 00:55:05 +04:00
|
|
|
}
|
|
|
|
|
2009-12-07 13:10:50 +03:00
|
|
|
/* Must be called only when object_name:filename doesn't exist. */
|
2019-06-27 12:28:49 +03:00
|
|
|
static void diagnose_invalid_oid_path(struct repository *r,
|
|
|
|
const char *prefix,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
const char *filename,
|
|
|
|
const struct object_id *tree_oid,
|
|
|
|
const char *object_name,
|
|
|
|
int object_name_len)
|
2009-12-07 13:10:50 +03:00
|
|
|
{
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
struct object_id oid;
|
2019-04-05 18:00:12 +03:00
|
|
|
unsigned short mode;
|
2009-12-07 13:10:50 +03:00
|
|
|
|
|
|
|
if (!prefix)
|
|
|
|
prefix = "";
|
|
|
|
|
2015-05-20 00:44:23 +03:00
|
|
|
if (file_exists(filename))
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("path '%s' exists on disk, but not in '%.*s'"),
|
2013-03-16 22:29:31 +04:00
|
|
|
filename, object_name_len, object_name);
|
2017-05-30 03:23:33 +03:00
|
|
|
if (is_missing_file_error(errno)) {
|
2014-06-20 01:26:56 +04:00
|
|
|
char *fullname = xstrfmt("%s%s", prefix, filename);
|
2009-12-07 13:10:50 +03:00
|
|
|
|
2019-06-27 12:28:49 +03:00
|
|
|
if (!get_tree_entry(r, tree_oid, fullname, &oid, &mode)) {
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("path '%s' exists, but not '%s'\n"
|
|
|
|
"hint: Did you mean '%.*s:%s' aka '%.*s:./%s'?"),
|
2009-12-07 13:10:50 +03:00
|
|
|
fullname,
|
|
|
|
filename,
|
2013-03-16 22:29:31 +04:00
|
|
|
object_name_len, object_name,
|
2011-03-31 13:17:34 +04:00
|
|
|
fullname,
|
2013-03-16 22:29:31 +04:00
|
|
|
object_name_len, object_name,
|
2011-03-31 13:17:34 +04:00
|
|
|
filename);
|
2009-12-07 13:10:50 +03:00
|
|
|
}
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("path '%s' does not exist in '%.*s'"),
|
2013-03-16 22:29:31 +04:00
|
|
|
filename, object_name_len, object_name);
|
2009-12-07 13:10:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Must be called only when :stage:filename doesn't exist. */
|
2019-04-16 12:33:34 +03:00
|
|
|
static void diagnose_invalid_index_path(struct repository *r,
|
2019-01-12 05:13:28 +03:00
|
|
|
int stage,
|
2009-12-07 13:10:50 +03:00
|
|
|
const char *prefix,
|
|
|
|
const char *filename)
|
|
|
|
{
|
2019-04-16 12:33:34 +03:00
|
|
|
struct index_state *istate = r->index;
|
Convert "struct cache_entry *" to "const ..." wherever possible
I attempted to make index_state->cache[] a "const struct cache_entry **"
to find out how existing entries in index are modified and where. The
question I have is what do we do if we really need to keep track of on-disk
changes in the index. The result is
- diff-lib.c: setting CE_UPTODATE
- name-hash.c: setting CE_HASHED
- preload-index.c, read-cache.c, unpack-trees.c and
builtin/update-index: obvious
- entry.c: write_entry() may refresh the checked out entry via
fill_stat_cache_info(). This causes "non-const struct cache_entry
*" in builtin/apply.c, builtin/checkout-index.c and
builtin/checkout.c
- builtin/ls-files.c: --with-tree changes stagemask and may set
CE_UPDATE
Of these, write_entry() and its call sites are probably most
interesting because it modifies on-disk info. But this is stat info
and can be retrieved via refresh, at least for porcelain
commands. Other just uses ce_flags for local purposes.
So, keeping track of "dirty" entries is just a matter of setting a
flag in index modification functions exposed by read-cache.c. Except
unpack-trees, the rest of the code base does not do anything funny
behind read-cache's back.
The actual patch is less valueable than the summary above. But if
anyone wants to re-identify the above sites. Applying this patch, then
this:
diff --git a/cache.h b/cache.h
index 430d021..1692891 100644
--- a/cache.h
+++ b/cache.h
@@ -267,7 +267,7 @@ static inline unsigned int canon_mode(unsigned int mode)
#define cache_entry_size(len) (offsetof(struct cache_entry,name) + (len) + 1)
struct index_state {
- struct cache_entry **cache;
+ const struct cache_entry **cache;
unsigned int version;
unsigned int cache_nr, cache_alloc, cache_changed;
struct string_list *resolve_undo;
will help quickly identify them without bogus warnings.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-09 19:29:00 +04:00
|
|
|
const struct cache_entry *ce;
|
2009-12-07 13:10:50 +03:00
|
|
|
int pos;
|
|
|
|
unsigned namelen = strlen(filename);
|
2015-09-25 00:07:52 +03:00
|
|
|
struct strbuf fullname = STRBUF_INIT;
|
2009-12-07 13:10:50 +03:00
|
|
|
|
|
|
|
if (!prefix)
|
|
|
|
prefix = "";
|
|
|
|
|
|
|
|
/* Wrong stage number? */
|
2019-01-12 05:13:28 +03:00
|
|
|
pos = index_name_pos(istate, filename, namelen);
|
2009-12-07 13:10:50 +03:00
|
|
|
if (pos < 0)
|
|
|
|
pos = -pos - 1;
|
2019-01-12 05:13:28 +03:00
|
|
|
if (pos < istate->cache_nr) {
|
|
|
|
ce = istate->cache[pos];
|
2010-02-28 18:49:15 +03:00
|
|
|
if (ce_namelen(ce) == namelen &&
|
|
|
|
!memcmp(ce->name, filename, namelen))
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("path '%s' is in the index, but not at stage %d\n"
|
|
|
|
"hint: Did you mean ':%d:%s'?"),
|
2010-02-28 18:49:15 +03:00
|
|
|
filename, stage,
|
|
|
|
ce_stage(ce), filename);
|
|
|
|
}
|
2009-12-07 13:10:50 +03:00
|
|
|
|
|
|
|
/* Confusion between relative and absolute filenames? */
|
2015-09-25 00:07:52 +03:00
|
|
|
strbuf_addstr(&fullname, prefix);
|
|
|
|
strbuf_addstr(&fullname, filename);
|
2019-01-12 05:13:28 +03:00
|
|
|
pos = index_name_pos(istate, fullname.buf, fullname.len);
|
2009-12-07 13:10:50 +03:00
|
|
|
if (pos < 0)
|
|
|
|
pos = -pos - 1;
|
2019-01-12 05:13:28 +03:00
|
|
|
if (pos < istate->cache_nr) {
|
|
|
|
ce = istate->cache[pos];
|
2015-09-25 00:07:52 +03:00
|
|
|
if (ce_namelen(ce) == fullname.len &&
|
|
|
|
!memcmp(ce->name, fullname.buf, fullname.len))
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("path '%s' is in the index, but not '%s'\n"
|
|
|
|
"hint: Did you mean ':%d:%s' aka ':%d:./%s'?"),
|
2015-09-25 00:07:52 +03:00
|
|
|
fullname.buf, filename,
|
|
|
|
ce_stage(ce), fullname.buf,
|
2011-03-31 13:17:34 +04:00
|
|
|
ce_stage(ce), filename);
|
2010-02-28 18:49:15 +03:00
|
|
|
}
|
2009-12-07 13:10:50 +03:00
|
|
|
|
2019-04-16 12:33:34 +03:00
|
|
|
if (repo_file_exists(r, filename))
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("path '%s' exists on disk, but not in the index"), filename);
|
2017-05-30 03:23:33 +03:00
|
|
|
if (is_missing_file_error(errno))
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("path '%s' does not exist (neither on disk nor in the index)"),
|
2009-12-07 13:10:50 +03:00
|
|
|
filename);
|
|
|
|
|
2015-09-25 00:07:52 +03:00
|
|
|
strbuf_release(&fullname);
|
2009-12-07 13:10:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-04-16 12:33:35 +03:00
|
|
|
static char *resolve_relative_path(struct repository *r, const char *rel)
|
2010-11-28 06:37:32 +03:00
|
|
|
{
|
2013-12-01 00:55:40 +04:00
|
|
|
if (!starts_with(rel, "./") && !starts_with(rel, "../"))
|
2010-11-28 06:37:32 +03:00
|
|
|
return NULL;
|
|
|
|
|
2019-04-16 12:33:35 +03:00
|
|
|
if (r != the_repository || !is_inside_work_tree())
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("relative path syntax can't be used outside working tree"));
|
2010-11-28 06:37:32 +03:00
|
|
|
|
|
|
|
/* die() inside prefix_path() if resolved path is outside worktree */
|
|
|
|
return prefix_path(startup_info->prefix,
|
|
|
|
startup_info->prefix ? strlen(startup_info->prefix) : 0,
|
|
|
|
rel);
|
|
|
|
}
|
|
|
|
|
2019-02-07 09:05:22 +03:00
|
|
|
static enum get_oid_result get_oid_with_context_1(struct repository *repo,
|
2019-01-12 05:13:28 +03:00
|
|
|
const char *name,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
unsigned flags,
|
|
|
|
const char *prefix,
|
|
|
|
struct object_id *oid,
|
|
|
|
struct object_context *oc)
|
2007-04-24 00:55:05 +04:00
|
|
|
{
|
|
|
|
int ret, bracket_depth;
|
2006-04-22 04:31:04 +04:00
|
|
|
int namelen = strlen(name);
|
|
|
|
const char *cp;
|
2017-07-14 02:49:29 +03:00
|
|
|
int only_to_die = flags & GET_OID_ONLY_TO_DIE;
|
2006-04-19 03:45:16 +04:00
|
|
|
|
2016-09-26 14:59:15 +03:00
|
|
|
if (only_to_die)
|
2017-07-14 02:49:29 +03:00
|
|
|
flags |= GET_OID_QUIETLY;
|
2016-09-26 14:59:15 +03:00
|
|
|
|
2010-06-09 21:02:06 +04:00
|
|
|
memset(oc, 0, sizeof(*oc));
|
|
|
|
oc->mode = S_IFINVALID;
|
2017-05-19 15:52:25 +03:00
|
|
|
strbuf_init(&oc->symlink_path, 0);
|
2019-04-16 12:33:32 +03:00
|
|
|
ret = get_oid_1(repo, name, namelen, oid, flags);
|
2006-04-22 04:31:04 +04:00
|
|
|
if (!ret)
|
|
|
|
return ret;
|
2012-07-02 21:32:11 +04:00
|
|
|
/*
|
2020-12-31 14:56:20 +03:00
|
|
|
* tree:path --> object name of path in tree
|
2010-11-28 06:37:32 +03:00
|
|
|
* :path -> object name of absolute path in index
|
|
|
|
* :./path -> object name of path relative to cwd in index
|
2006-04-22 04:31:04 +04:00
|
|
|
* :[0-3]:path -> object name of path in index at stage
|
2010-09-24 20:43:59 +04:00
|
|
|
* :/foo -> recent commit matching foo
|
2006-04-22 04:31:04 +04:00
|
|
|
*/
|
|
|
|
if (name[0] == ':') {
|
|
|
|
int stage = 0;
|
Convert "struct cache_entry *" to "const ..." wherever possible
I attempted to make index_state->cache[] a "const struct cache_entry **"
to find out how existing entries in index are modified and where. The
question I have is what do we do if we really need to keep track of on-disk
changes in the index. The result is
- diff-lib.c: setting CE_UPTODATE
- name-hash.c: setting CE_HASHED
- preload-index.c, read-cache.c, unpack-trees.c and
builtin/update-index: obvious
- entry.c: write_entry() may refresh the checked out entry via
fill_stat_cache_info(). This causes "non-const struct cache_entry
*" in builtin/apply.c, builtin/checkout-index.c and
builtin/checkout.c
- builtin/ls-files.c: --with-tree changes stagemask and may set
CE_UPDATE
Of these, write_entry() and its call sites are probably most
interesting because it modifies on-disk info. But this is stat info
and can be retrieved via refresh, at least for porcelain
commands. Other just uses ce_flags for local purposes.
So, keeping track of "dirty" entries is just a matter of setting a
flag in index modification functions exposed by read-cache.c. Except
unpack-trees, the rest of the code base does not do anything funny
behind read-cache's back.
The actual patch is less valueable than the summary above. But if
anyone wants to re-identify the above sites. Applying this patch, then
this:
diff --git a/cache.h b/cache.h
index 430d021..1692891 100644
--- a/cache.h
+++ b/cache.h
@@ -267,7 +267,7 @@ static inline unsigned int canon_mode(unsigned int mode)
#define cache_entry_size(len) (offsetof(struct cache_entry,name) + (len) + 1)
struct index_state {
- struct cache_entry **cache;
+ const struct cache_entry **cache;
unsigned int version;
unsigned int cache_nr, cache_alloc, cache_changed;
struct string_list *resolve_undo;
will help quickly identify them without bogus warnings.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-09 19:29:00 +04:00
|
|
|
const struct cache_entry *ce;
|
2010-11-28 06:37:32 +03:00
|
|
|
char *new_path = NULL;
|
2006-04-22 04:31:04 +04:00
|
|
|
int pos;
|
fix overslow :/no-such-string-ever-existed diagnostics
"git cmd :/no-such-string-ever-existed" runs an extra round of get_sha1()
since 009fee4 (Detailed diagnosis when parsing an object name fails.,
2009-12-07). Once without error diagnosis to see there is no commit with
such a string in the log message (hence "it cannot be a ref"), and after
seeing that :/no-such-string-ever-existed is not a filename (hence "it
cannot be a path, either"), another time to give "better diagnosis".
The thing is, the second time it runs, we already know that traversing the
history all the way down to the root will _not_ find any matching commit.
Rename misguided "gently" parameter, which is turned off _only_ when the
"detailed diagnosis" codepath knows that it cannot be a ref and making the
call only for the caller to die with a message. Flip its meaning (and
adjust the callers) and call it "only_to_die", which is not a great name,
but it describes far more clearly what the codepaths that switches their
behaviour based on this variable do.
On my box, the command spends ~1.8 seconds without the patch to make the
report; with the patch it spends ~1.12 seconds.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-05-10 23:02:54 +04:00
|
|
|
if (!only_to_die && namelen > 2 && name[1] == '/') {
|
2019-04-16 12:33:33 +03:00
|
|
|
struct handle_one_ref_cb cb;
|
2010-12-13 06:01:14 +03:00
|
|
|
struct commit_list *list = NULL;
|
2015-05-25 21:38:28 +03:00
|
|
|
|
2019-04-16 12:33:33 +03:00
|
|
|
cb.repo = repo;
|
|
|
|
cb.list = &list;
|
2020-04-10 03:03:45 +03:00
|
|
|
refs_for_each_ref(get_main_ref_store(repo), handle_one_ref, &cb);
|
repository: mark the "refs" pointer as private
The "refs" pointer in a struct repository starts life as NULL, but then
is lazily initialized when it is accessed via get_main_ref_store().
However, it's easy for calling code to forget this and access it
directly, leading to code which works _some_ of the time, but fails if
it is called before anybody else accesses the refs.
This was the cause of the bug fixed by 5ff4b920eb (sha1-name: do not
assume that the ref store is initialized, 2020-04-09). In order to
prevent similar bugs, let's more clearly mark the "refs" field as
private.
In addition to helping future code, the name change will help us audit
any existing direct uses. Besides get_main_ref_store() itself, it turns
out there is only one. But we know it's OK as it is on the line directly
after the fix from 5ff4b920eb, which will have initialized the pointer.
However it's still a good idea for it to model the proper use of the
accessing function, so we'll convert it.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-10 06:04:11 +03:00
|
|
|
refs_head_ref(get_main_ref_store(repo), handle_one_ref, &cb);
|
2014-08-21 22:30:29 +04:00
|
|
|
commit_list_sort_by_date(&list);
|
2019-04-16 12:33:29 +03:00
|
|
|
return get_oid_oneline(repo, name + 2, oid, list);
|
2010-12-13 06:01:14 +03:00
|
|
|
}
|
2006-04-22 04:31:04 +04:00
|
|
|
if (namelen < 3 ||
|
|
|
|
name[2] != ':' ||
|
|
|
|
name[1] < '0' || '3' < name[1])
|
|
|
|
cp = name + 1;
|
|
|
|
else {
|
|
|
|
stage = name[1] - '0';
|
|
|
|
cp = name + 3;
|
2006-04-19 03:45:16 +04:00
|
|
|
}
|
2019-04-16 12:33:35 +03:00
|
|
|
new_path = resolve_relative_path(repo, cp);
|
2010-12-10 00:38:05 +03:00
|
|
|
if (!new_path) {
|
|
|
|
namelen = namelen - (cp - name);
|
|
|
|
} else {
|
|
|
|
cp = new_path;
|
|
|
|
namelen = strlen(cp);
|
|
|
|
}
|
2010-06-09 21:02:06 +04:00
|
|
|
|
2017-07-14 02:49:29 +03:00
|
|
|
if (flags & GET_OID_RECORD_PATH)
|
2017-05-19 15:54:43 +03:00
|
|
|
oc->path = xstrdup(cp);
|
2010-06-09 21:02:06 +04:00
|
|
|
|
get_oid: handle NULL repo->index
When get_oid() and its helpers see an index name like ":.gitmodules",
they try to load the index on demand, like:
if (repo->index->cache)
repo_read_index(repo);
However, that misses the case when "repo->index" itself is NULL; we'll
segfault in the conditional.
This never happens with the_repository; there we always point its index
field to &the_index. But a submodule repository may have a NULL index
field until somebody calls repo_read_index().
This bug is triggered by t7411, but it was hard to notice because it's
in an expect_failure block. That test was added by 2b1257e463 (t/helper:
add test-submodule-nested-repo-config, 2018-10-25). Back then we had no
easy way to access the .gitmodules blob of a submodule repo, so we
expected (and got) an error message to that effect. Later, d9b8b8f896
(submodule-config.c: use repo_get_oid for reading .gitmodules,
2019-04-16) started looking in the correct repo, which is when we
started triggering the segfault.
With this fix, the test starts passing (once we clean it up as its
comment instructs).
Note that as far as I know, this bug could not be triggered outside of
the test suite. It requires resolving an index name in a submodule, and
all of the code paths (aside from test-tool) which do that either load
the index themselves, or always pass the_repository.
Ultimately it comes from 3a7a698e93 (sha1-name.c: remove implicit
dependency on the_index, 2019-01-12), which replaced a check of
"the_index.cache" with "repo->index->cache". So even if there is another
way to trigger it, it wouldn't affect any versions before then.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-05-14 16:54:55 +03:00
|
|
|
if (!repo->index || !repo->index->cache)
|
2019-04-16 12:33:36 +03:00
|
|
|
repo_read_index(repo);
|
2019-01-12 05:13:28 +03:00
|
|
|
pos = index_name_pos(repo->index, cp, namelen);
|
2006-04-22 04:31:04 +04:00
|
|
|
if (pos < 0)
|
|
|
|
pos = -pos - 1;
|
2019-01-12 05:13:28 +03:00
|
|
|
while (pos < repo->index->cache_nr) {
|
|
|
|
ce = repo->index->cache[pos];
|
2006-04-22 04:31:04 +04:00
|
|
|
if (ce_namelen(ce) != namelen ||
|
|
|
|
memcmp(ce->name, cp, namelen))
|
|
|
|
break;
|
|
|
|
if (ce_stage(ce) == stage) {
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
oidcpy(oid, &ce->oid);
|
2010-09-29 15:35:24 +04:00
|
|
|
oc->mode = ce->ce_mode;
|
2010-11-28 06:37:32 +03:00
|
|
|
free(new_path);
|
2006-04-22 04:31:04 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2006-05-09 02:44:06 +04:00
|
|
|
pos++;
|
2006-04-22 04:31:04 +04:00
|
|
|
}
|
fix overslow :/no-such-string-ever-existed diagnostics
"git cmd :/no-such-string-ever-existed" runs an extra round of get_sha1()
since 009fee4 (Detailed diagnosis when parsing an object name fails.,
2009-12-07). Once without error diagnosis to see there is no commit with
such a string in the log message (hence "it cannot be a ref"), and after
seeing that :/no-such-string-ever-existed is not a filename (hence "it
cannot be a path, either"), another time to give "better diagnosis".
The thing is, the second time it runs, we already know that traversing the
history all the way down to the root will _not_ find any matching commit.
Rename misguided "gently" parameter, which is turned off _only_ when the
"detailed diagnosis" codepath knows that it cannot be a ref and making the
call only for the caller to die with a message. Flip its meaning (and
adjust the callers) and call it "only_to_die", which is not a great name,
but it describes far more clearly what the codepaths that switches their
behaviour based on this variable do.
On my box, the command spends ~1.8 seconds without the patch to make the
report; with the patch it spends ~1.12 seconds.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-05-10 23:02:54 +04:00
|
|
|
if (only_to_die && name[1] && name[1] != '/')
|
2019-04-16 12:33:34 +03:00
|
|
|
diagnose_invalid_index_path(repo, stage, prefix, cp);
|
2010-11-28 06:37:32 +03:00
|
|
|
free(new_path);
|
2006-04-22 04:31:04 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2006-05-19 11:29:43 +04:00
|
|
|
for (cp = name, bracket_depth = 0; *cp; cp++) {
|
|
|
|
if (*cp == '{')
|
|
|
|
bracket_depth++;
|
|
|
|
else if (bracket_depth && *cp == '}')
|
|
|
|
bracket_depth--;
|
|
|
|
else if (!bracket_depth && *cp == ':')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*cp == ':') {
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
struct object_id tree_oid;
|
2013-03-16 22:29:31 +04:00
|
|
|
int len = cp - name;
|
2016-09-26 14:59:41 +03:00
|
|
|
unsigned sub_flags = flags;
|
|
|
|
|
2017-07-14 02:49:29 +03:00
|
|
|
sub_flags &= ~GET_OID_DISAMBIGUATORS;
|
|
|
|
sub_flags |= GET_OID_TREEISH;
|
2016-09-26 14:59:41 +03:00
|
|
|
|
2019-04-16 12:33:32 +03:00
|
|
|
if (!get_oid_1(repo, name, len, &tree_oid, sub_flags)) {
|
2009-12-07 13:10:50 +03:00
|
|
|
const char *filename = cp+1;
|
2010-11-28 06:37:32 +03:00
|
|
|
char *new_filename = NULL;
|
|
|
|
|
2019-04-16 12:33:35 +03:00
|
|
|
new_filename = resolve_relative_path(repo, filename);
|
2010-11-28 06:37:32 +03:00
|
|
|
if (new_filename)
|
|
|
|
filename = new_filename;
|
2017-07-14 02:49:29 +03:00
|
|
|
if (flags & GET_OID_FOLLOW_SYMLINKS) {
|
2019-06-27 12:28:50 +03:00
|
|
|
ret = get_tree_entry_follow_symlinks(repo, &tree_oid,
|
2018-05-02 03:25:40 +03:00
|
|
|
filename, oid, &oc->symlink_path,
|
2015-05-20 20:03:39 +03:00
|
|
|
&oc->mode);
|
|
|
|
} else {
|
2019-06-27 12:28:49 +03:00
|
|
|
ret = get_tree_entry(repo, &tree_oid, filename, oid,
|
2018-03-12 05:27:51 +03:00
|
|
|
&oc->mode);
|
2015-05-20 20:03:39 +03:00
|
|
|
if (ret && only_to_die) {
|
2019-06-27 12:28:49 +03:00
|
|
|
diagnose_invalid_oid_path(repo, prefix,
|
2015-05-20 20:03:39 +03:00
|
|
|
filename,
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
&tree_oid,
|
2015-05-20 20:03:39 +03:00
|
|
|
name, len);
|
|
|
|
}
|
2009-12-07 13:10:50 +03:00
|
|
|
}
|
2017-07-14 02:49:29 +03:00
|
|
|
if (flags & GET_OID_RECORD_PATH)
|
2017-05-19 15:54:43 +03:00
|
|
|
oc->path = xstrdup(filename);
|
2010-06-09 21:02:06 +04:00
|
|
|
|
2010-11-28 06:37:32 +03:00
|
|
|
free(new_filename);
|
2009-12-07 13:10:50 +03:00
|
|
|
return ret;
|
|
|
|
} else {
|
fix overslow :/no-such-string-ever-existed diagnostics
"git cmd :/no-such-string-ever-existed" runs an extra round of get_sha1()
since 009fee4 (Detailed diagnosis when parsing an object name fails.,
2009-12-07). Once without error diagnosis to see there is no commit with
such a string in the log message (hence "it cannot be a ref"), and after
seeing that :/no-such-string-ever-existed is not a filename (hence "it
cannot be a path, either"), another time to give "better diagnosis".
The thing is, the second time it runs, we already know that traversing the
history all the way down to the root will _not_ find any matching commit.
Rename misguided "gently" parameter, which is turned off _only_ when the
"detailed diagnosis" codepath knows that it cannot be a ref and making the
call only for the caller to die with a message. Flip its meaning (and
adjust the callers) and call it "only_to_die", which is not a great name,
but it describes far more clearly what the codepaths that switches their
behaviour based on this variable do.
On my box, the command spends ~1.8 seconds without the patch to make the
report; with the patch it spends ~1.12 seconds.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-05-10 23:02:54 +04:00
|
|
|
if (only_to_die)
|
2020-01-25 03:13:01 +03:00
|
|
|
die(_("invalid object name '%.*s'."), len, name);
|
2009-12-07 13:10:50 +03:00
|
|
|
}
|
2006-04-19 03:45:16 +04:00
|
|
|
}
|
|
|
|
return ret;
|
2005-08-04 09:15:49 +04:00
|
|
|
}
|
2012-07-02 21:19:35 +04:00
|
|
|
|
2012-07-02 22:01:25 +04:00
|
|
|
/*
|
|
|
|
* Call this function when you know "name" given by the end user must
|
|
|
|
* name an object but it doesn't; the function _may_ die with a better
|
|
|
|
* diagnostic message than "no such object 'name'", e.g. "Path 'doc' does not
|
|
|
|
* exist in 'HEAD'" when given "HEAD:doc", or it may return in which case
|
|
|
|
* you have a chance to diagnose the error further.
|
|
|
|
*/
|
2019-04-16 12:33:39 +03:00
|
|
|
void maybe_die_on_misspelt_object_name(struct repository *r,
|
|
|
|
const char *name,
|
|
|
|
const char *prefix)
|
2012-07-02 21:19:35 +04:00
|
|
|
{
|
|
|
|
struct object_context oc;
|
sha1_name: convert get_sha1* to get_oid*
Now that all the callers of get_sha1 directly or indirectly use struct
object_id, rename the functions starting with get_sha1 to start with
get_oid. Convert the internals in sha1_name.c to use struct object_id
as well, and eliminate explicit length checks where possible. Convert a
use of 40 in get_oid_basic to GIT_SHA1_HEXSZ.
Outside of sha1_name.c and cache.h, this transition was made with the
following semantic patch:
@@
expression E1, E2;
@@
- get_sha1(E1, E2.hash)
+ get_oid(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1(E1, E2->hash)
+ get_oid(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2.hash)
+ get_oid_committish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_committish(E1, E2->hash)
+ get_oid_committish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2.hash)
+ get_oid_treeish(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_treeish(E1, E2->hash)
+ get_oid_treeish(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2.hash)
+ get_oid_commit(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_commit(E1, E2->hash)
+ get_oid_commit(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2.hash)
+ get_oid_tree(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_tree(E1, E2->hash)
+ get_oid_tree(E1, E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2.hash)
+ get_oid_blob(E1, &E2)
@@
expression E1, E2;
@@
- get_sha1_blob(E1, E2->hash)
+ get_oid_blob(E1, E2)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3.hash, E4)
+ get_oid_with_context(E1, E2, &E3, E4)
@@
expression E1, E2, E3, E4;
@@
- get_sha1_with_context(E1, E2, E3->hash, E4)
+ get_oid_with_context(E1, E2, E3, E4)
Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-14 02:49:28 +03:00
|
|
|
struct object_id oid;
|
2019-04-16 12:33:39 +03:00
|
|
|
get_oid_with_context_1(r, name, GET_OID_ONLY_TO_DIE,
|
2019-01-12 05:13:28 +03:00
|
|
|
prefix, &oid, &oc);
|
2012-07-02 22:01:25 +04:00
|
|
|
}
|
|
|
|
|
2019-02-12 15:43:23 +03:00
|
|
|
enum get_oid_result get_oid_with_context(struct repository *repo,
|
|
|
|
const char *str,
|
|
|
|
unsigned flags,
|
|
|
|
struct object_id *oid,
|
|
|
|
struct object_context *oc)
|
2012-07-02 21:19:35 +04:00
|
|
|
{
|
2017-07-14 02:49:29 +03:00
|
|
|
if (flags & GET_OID_FOLLOW_SYMLINKS && flags & GET_OID_ONLY_TO_DIE)
|
2020-12-31 14:56:20 +03:00
|
|
|
BUG("incompatible flags for get_oid_with_context");
|
2019-01-12 05:13:28 +03:00
|
|
|
return get_oid_with_context_1(repo, str, flags, NULL, oid, oc);
|
2012-07-02 21:19:35 +04:00
|
|
|
}
|