commit - d69bcdf7cbe646a8ad22a81f8665f3bd2e39e189
commit + e09a504cc5b72ff4eca5d539b6fb50c8d01d0036
blob - a4975d670ed06aa6ed6696642cd7e23b2e0a0ee9
blob + 63ce30e7bcc45b4859409015ccaceab0666be898
--- got/got.c
+++ got/got.c
if (commit_id_str) {
struct got_object_id *commit_id;
- error = got_object_resolve_id_str(&commit_id, repo,
- commit_id_str);
+ error = got_repo_match_object_id_prefix(&commit_id,
+ commit_id_str, repo);
if (error != NULL)
goto done;
error = check_linear_ancestry(commit_id,
if (error != NULL)
goto done;
} else {
- error = got_object_resolve_id_str(&commit_id, repo,
- commit_id_str);
+ error = got_repo_match_object_id_prefix(&commit_id,
+ commit_id_str, repo);
if (error != NULL)
goto done;
}
goto done;
}
if (commit == NULL) {
- error = got_object_resolve_id_str(&id, repo,
- start_commit);
+ error = got_repo_match_object_id_prefix(&id,
+ start_commit, repo);
if (error != NULL)
return error;
}
goto done;
}
- error = got_object_resolve_id_str(&id1, repo, id_str1);
+ error = got_repo_match_object_id_prefix(&id1, id_str1, repo);
if (error) {
struct got_reference *ref;
if (error->code != GOT_ERR_BAD_OBJ_ID_STR)
}
}
- error = got_object_resolve_id_str(&id2, repo, id_str2);
+ error = got_repo_match_object_id_prefix(&id2, id_str2, repo);
if (error) {
struct got_reference *ref;
if (error->code != GOT_ERR_BAD_OBJ_ID_STR)
if (error != NULL)
goto done;
} else {
- error = got_object_resolve_id_str(&commit_id, repo,
- commit_id_str);
+ error = got_repo_match_object_id_prefix(&commit_id,
+ commit_id_str, repo);
if (error != NULL)
goto done;
}
if (error != NULL)
goto done;
} else {
- error = got_object_resolve_id_str(&commit_id, repo,
- commit_id_str);
+ error = got_repo_match_object_id_prefix(&commit_id,
+ commit_id_str, repo);
if (error != NULL)
goto done;
}
struct got_object_id *id;
struct got_reference *ref = NULL;
- err = got_object_resolve_id_str(&id, repo, target);
+ err = got_repo_match_object_id_prefix(&id, target, repo);
if (err) {
struct got_reference *target_ref;
if (error)
goto done;
- error = got_object_resolve_id_str(&commit_id, repo, argv[0]);
+ error = got_repo_match_object_id_prefix(&commit_id, argv[0], repo);
if (error != NULL) {
struct got_reference *ref;
if (error->code != GOT_ERR_BAD_OBJ_ID_STR)
if (error)
goto done;
- error = got_object_resolve_id_str(&commit_id, repo, argv[0]);
+ error = got_repo_match_object_id_prefix(&commit_id, argv[0], repo);
if (error != NULL) {
struct got_reference *ref;
if (error->code != GOT_ERR_BAD_OBJ_ID_STR)
blob - c05ac929d21262fe260f6843312f25459fc4a06d
blob + 83b7c99d663d7a35621aa740a8b3f4da13281612
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_BAD_OBJ_HDR 10
#define GOT_ERR_OBJ_TYPE 11
#define GOT_ERR_BAD_OBJ_DATA 12
-/* 13 is currently free for re-use */
+#define GOT_ERR_AMBIGUOUS_ID 13
#define GOT_ERR_BAD_PACKIDX 14
#define GOT_ERR_PACKIDX_CSUM 15
#define GOT_ERR_BAD_PACKFILE 16
{ GOT_ERR_BAD_OBJ_HDR, "bad object header" },
{ GOT_ERR_OBJ_TYPE, "wrong type of object" },
{ GOT_ERR_BAD_OBJ_DATA, "bad object data" },
- { 13, "unused error code" },
+ { GOT_ERR_AMBIGUOUS_ID, "ambiguous object ID" },
{ GOT_ERR_BAD_PACKIDX, "bad pack index file" },
{ GOT_ERR_PACKIDX_CSUM, "pack index file checksum error" },
{ GOT_ERR_BAD_PACKFILE, "bad pack file" },
blob - 0b61b49e3ed0680170a01636840b554aac156059
blob + 69c2e095c3af4282d19b75475fcff80fe12aeef5
--- include/got_repository.h
+++ include/got_repository.h
/* Create a new repository in an empty directory at a specified path. */
const struct got_error *got_repo_init(const char *);
+
+/* Attempt to find a unique object ID for a given ID string prefix. */
+const struct got_error *got_repo_match_object_id_prefix(struct got_object_id **,
+ const char *, struct got_repository *);
blob - 449f4a66c5e45ada327bc786016b0b7788668394
blob + 241a9411ba3a191b9ceafd49e0fec3cd038b2049
--- lib/diff.c
+++ lib/diff.c
#include <sha1.h>
#include <zlib.h>
-#include "got_repository.h"
#include "got_object.h"
+#include "got_repository.h"
#include "got_error.h"
#include "got_diff.h"
#include "got_opentemp.h"
blob - 34beeb2b7345dac2a513a297aab77a4a94811563
blob + 7af741d237c7cd84aca6789c32dc4cdf3bb5237a
--- lib/got_lib_pack.h
+++ lib/got_lib_pack.h
const char *, int);
const struct got_error* got_packidx_close(struct got_packidx *);
int got_packidx_get_object_idx(struct got_packidx *, struct got_object_id *);
+typedef const struct got_error *(*got_packidx_for_each_id_cb)(void *,
+ struct got_object_id *);
+const struct got_error *got_packidx_for_each_id(struct got_packidx *,
+ got_packidx_for_each_id_cb cb, void *);
const struct got_error *got_packfile_open_object(struct got_object **,
struct got_pack *, struct got_packidx *, int, struct got_object_id *);
blob - 691ab915f783045757051241faacca38bd22898f
blob + 60a273ea713af45d42943ac3274ba6081c775576
--- lib/object.c
+++ lib/object.c
}
return err;
}
-
blob - 9f38ab305851d89c4ee68b2ae45ad8935d7a6d87
blob + 269e6fa733cf1a2955a5e341a8d46504352492c9
--- lib/pack.c
+++ lib/pack.c
}
const struct got_error *
+got_packidx_for_each_id(struct got_packidx *packidx,
+ got_packidx_for_each_id_cb cb, void *cb_arg)
+{
+ const struct got_error *err = NULL;
+ uint32_t nobj = betoh32(packidx->hdr.fanout_table[0xff]);
+ struct got_packidx_object_id *oid;
+ struct got_object_id id;
+ int i;
+
+ for (i = 0; i < nobj; i++) {
+ oid = &packidx->hdr.sorted_ids[i];
+ memcpy(&id, oid->sha1, SHA1_DIGEST_LENGTH);
+ err = cb(cb_arg, &id);
+ if (err)
+ break;
+ }
+
+ return err;
+}
+
+const struct got_error *
got_pack_stop_privsep_child(struct got_pack *pack)
{
const struct got_error *err = NULL;
blob - 34d0da428d84d9053008e21e8223ac41ed646d33
blob + f4cf79809502ced018e0ec153ae2240982059eb5
--- lib/repository.c
+++ lib/repository.c
#include <sys/mman.h>
#include <sys/syslimits.h>
+#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <dirent.h>
#include "got_lib_pack.h"
#include "got_lib_privsep.h"
#include "got_lib_worktree.h"
+#include "got_lib_sha1.h"
#include "got_lib_object_cache.h"
#include "got_lib_repository.h"
return err;
return NULL;
+}
+
+struct match_packidx_id_args {
+ const char *id_str_prefix;
+ struct got_object_id *unique_id;
+};
+
+static const struct got_error *
+match_packidx_id(void *arg, struct got_object_id *id)
+{
+ const struct got_error *err;
+ struct match_packidx_id_args *a = arg;
+ char *id_str;
+
+ err = got_object_id_str(&id_str, id);
+ if (err)
+ return err;
+
+ if (strncmp(a->id_str_prefix, id_str, strlen(a->id_str_prefix)) == 0) {
+ if (a->unique_id == NULL) {
+ a->unique_id = got_object_id_dup(id);
+ if (a->unique_id == NULL)
+ err = got_error_from_errno("got_object_id_dup");
+ }
+ }
+
+ free(id_str);
+ return err;
+}
+
+static const struct got_error *
+match_packed_object_id_prefix(struct got_object_id **unique_id,
+ struct got_repository *repo, const char *id_str_prefix)
+{
+ const struct got_error *err = NULL;
+ struct match_packidx_id_args args;
+ char *path_packdir;
+ DIR *packdir;
+ struct dirent *dent;
+ char *path_packidx;
+
+ *unique_id = NULL;
+
+ path_packdir = got_repo_get_path_objects_pack(repo);
+ if (path_packdir == NULL)
+ return got_error_from_errno("got_repo_get_path_objects_pack");
+
+ packdir = opendir(path_packdir);
+ if (packdir == NULL) {
+ err = got_error_from_errno2("opendir", path_packdir);
+ goto done;
+ }
+
+ while ((dent = readdir(packdir)) != NULL) {
+ struct got_packidx *packidx;
+ const struct got_error *cb_err;
+
+ if (!is_packidx_filename(dent->d_name, dent->d_namlen))
+ continue;
+
+ if (asprintf(&path_packidx, "%s/%s", path_packdir,
+ dent->d_name) == -1) {
+ err = got_error_from_errno("asprintf");
+ goto done;
+ }
+
+ err = got_packidx_open(&packidx, path_packidx, 0);
+ free(path_packidx);
+ if (err)
+ goto done;
+
+ args.id_str_prefix = id_str_prefix;
+ args.unique_id = NULL;
+ cb_err = got_packidx_for_each_id(packidx, match_packidx_id,
+ &args);
+ err = got_packidx_close(packidx);
+ if (err)
+ break;
+ if (cb_err) {
+ err = cb_err;
+ break;
+ }
+
+ if (args.unique_id) {
+ if (*unique_id == NULL)
+ *unique_id = args.unique_id;
+ else {
+ err = got_error(GOT_ERR_AMBIGUOUS_ID);
+ break;
+ }
+ }
+ }
+done:
+ free(path_packdir);
+ if (packdir && closedir(packdir) != 0 && err == NULL)
+ err = got_error_from_errno("closedir");
+ if (err) {
+ free(*unique_id);
+ *unique_id = NULL;
+ }
+ return err;
+}
+
+static const struct got_error *
+match_object_id(struct got_object_id **unique_id, const char *path_objects,
+ const char *object_dir, const char *id_str_prefix,
+ struct got_repository *repo)
+{
+ const struct got_error *err = NULL;
+ char *path;
+ DIR *dir = NULL;
+ struct dirent *dent;
+ struct got_object_id id;
+ int i;
+
+ for (i = 0; i < strlen(id_str_prefix); i++) {
+ if (isxdigit((unsigned char)id_str_prefix[i]))
+ continue;
+ return got_error(GOT_ERR_BAD_OBJ_ID_STR);
+ }
+
+ /* Search pack index. */
+ err = match_packed_object_id_prefix(unique_id, repo, id_str_prefix);
+ if (err)
+ return err;
+
+ /* Search on-disk directories. */
+ if (asprintf(&path, "%s/%s", path_objects, object_dir) == -1) {
+ err = got_error_from_errno("asprintf");
+ goto done;
+ }
+
+ dir = opendir(path);
+ if (dir == NULL) {
+ err = got_error_from_errno2("opendir", path);
+ goto done;
+ }
+ while ((dent = readdir(dir)) != NULL) {
+ char *id_str;
+ if (strcmp(dent->d_name, ".") == 0 ||
+ strcmp(dent->d_name, "..") == 0)
+ continue;
+
+ if (asprintf(&id_str, "%s%s", object_dir, dent->d_name) == -1) {
+ err = got_error_from_errno("asprintf");
+ goto done;
+ }
+
+ if (!got_parse_sha1_digest(id.sha1, id_str))
+ continue;
+
+ if (strncmp(id_str_prefix, id_str,
+ strlen(id_str_prefix)) != 0) {
+ free(id_str);
+ continue;
+ }
+
+ if (*unique_id == NULL) {
+ *unique_id = got_object_id_dup(&id);
+ if (*unique_id == NULL) {
+ err = got_error_from_errno("got_object_id_dup");
+ free(id_str);
+ goto done;
+ }
+ } else {
+ err = got_error(GOT_ERR_AMBIGUOUS_ID);
+ free(id_str);
+ goto done;
+ }
+ }
+
+ if (err == NULL && *unique_id == NULL)
+ err = got_error(GOT_ERR_NO_OBJ);
+done:
+ if (err) {
+ free(*unique_id);
+ *unique_id = NULL;
+ }
+ if (dir && closedir(dir) != 0 && err == NULL)
+ err = got_error_from_errno("closedir");
+ free(path);
+ return err;
}
+
+const struct got_error *
+got_repo_match_object_id_prefix(struct got_object_id **id, const char *id_str_prefix,
+ struct got_repository *repo)
+{
+ const struct got_error *err = NULL;
+ char *path_objects = got_repo_get_path_objects(repo);
+ char *object_dir = NULL;
+ size_t len;
+
+ len = strlen(id_str_prefix);
+ if (len >= 2) {
+ object_dir = strndup(id_str_prefix, 2);
+ if (object_dir == NULL)
+ return got_error_from_errno("strdup");
+ err = match_object_id(id, path_objects, object_dir,
+ id_str_prefix, repo);
+ } else if (len == 1) {
+ int i;
+ for (i = 0; i < 0xf; i++) {
+ if (asprintf(&object_dir, "%s%.1x", id_str_prefix, i)
+ == -1)
+ return got_error_from_errno("asprintf");
+ err = match_object_id(id, path_objects, object_dir,
+ id_str_prefix, repo);
+ if (err)
+ break;
+ }
+ } else
+ return got_error(GOT_ERR_BAD_OBJ_ID_STR);
+
+ free(object_dir);
+ return err;
+}
blob - fc0bb7562d2d4c401739ecf6172c5813f1448b59
blob + 79ae802838b0dee98d1c9dcf060003faa4c58629
--- tog/tog.c
+++ tog/tog.c
got_worktree_get_head_ref_name(worktree) : GOT_REF_HEAD,
repo);
else
- error = got_object_resolve_id_str(&start_id, repo,
- start_commit);
+ error = got_repo_match_object_id_prefix(&start_id,
+ start_commit, repo);
if (error != NULL)
goto done;
if (error)
goto done;
- error = got_object_resolve_id_str(&id1, repo, id_str1);
+ error = got_repo_match_object_id_prefix(&id1, id_str1, repo);
if (error)
goto done;
- error = got_object_resolve_id_str(&id2, repo, id_str2);
+ error = got_repo_match_object_id_prefix(&id2, id_str2, repo);
if (error)
goto done;
error = got_ref_resolve(&commit_id, repo, head_ref);
got_ref_close(head_ref);
} else {
- error = got_object_resolve_id_str(&commit_id, repo,
- commit_id_str);
+ error = got_repo_match_object_id_prefix(&commit_id,
+ commit_id_str, repo);
}
if (error != NULL)
goto done;
if (commit_id_arg == NULL)
error = get_head_commit_id(&commit_id, GOT_REF_HEAD, repo);
else
- error = got_object_resolve_id_str(&commit_id, repo,
- commit_id_arg);
+ error = got_repo_match_object_id_prefix(&commit_id,
+ commit_id_arg, repo);
if (error != NULL)
goto done;