odb/source: support writing alternates when creating the database
Add the ability to write alternates when creating the object database. This change allows us to remove the `write_alternates()` callback in a subsequent patch. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>jch
parent
2e26876b48
commit
d540449b15
|
|
@ -18,6 +18,7 @@
|
|||
#include "run-command.h"
|
||||
#include "strbuf.h"
|
||||
#include "string-list.h"
|
||||
#include "strmap.h"
|
||||
#include "strvec.h"
|
||||
#include "tree.h"
|
||||
#include "write-or-die.h"
|
||||
|
|
@ -51,9 +52,14 @@ static void odb_source_files_close(struct odb_source *source)
|
|||
odb_source_close(&files->packed->base);
|
||||
}
|
||||
|
||||
static int odb_source_files_create_on_disk(struct odb_source *source)
|
||||
static int odb_source_files_create_on_disk(struct odb_source *source,
|
||||
const struct odb_create_on_disk_options *opts)
|
||||
{
|
||||
struct lock_file alternates_lock = LOCK_INIT;
|
||||
struct strbuf path = STRBUF_INIT;
|
||||
struct strset seen = STRSET_INIT;
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
int ret;
|
||||
|
||||
safe_create_dir(source->odb->repo, source->path, 1);
|
||||
|
||||
|
|
@ -64,8 +70,74 @@ static int odb_source_files_create_on_disk(struct odb_source *source)
|
|||
strbuf_addf(&path, "%s/info", source->path);
|
||||
safe_create_dir(source->odb->repo, path.buf, 1);
|
||||
|
||||
if (opts->alternates && opts->alternates->nr) {
|
||||
FILE *alternates, *orig;
|
||||
|
||||
strbuf_reset(&path);
|
||||
strbuf_addf(&path, "%s/info/alternates", source->path);
|
||||
|
||||
repo_hold_lock_file_for_update(source->odb->repo, &alternates_lock,
|
||||
path.buf, LOCK_DIE_ON_ERROR);
|
||||
|
||||
alternates = fdopen_lock_file(&alternates_lock, "w");
|
||||
if (!alternates) {
|
||||
ret = error_errno(_("unable to fdopen alternates lockfile"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* The alternates file may already exist, e.g. when it has been
|
||||
* seeded from a template directory. Read any preexisting
|
||||
* entries so that we don't end up writing duplicates.
|
||||
*/
|
||||
orig = fopen(path.buf, "r");
|
||||
if (orig) {
|
||||
while (strbuf_getline(&line, orig) != EOF) {
|
||||
strset_add(&seen, line.buf);
|
||||
fprintf(alternates, "%s\n", line.buf);
|
||||
}
|
||||
|
||||
if (ferror(orig)) {
|
||||
ret = error_errno(_("unable to read alternates file"));
|
||||
fclose(orig);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fclose(orig);
|
||||
} else if (errno != ENOENT) {
|
||||
ret = error_errno(_("unable to read alternates file"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < opts->alternates->nr; i++) {
|
||||
const char *alternate = opts->alternates->v[i];
|
||||
if (!strset_add(&seen, alternate))
|
||||
continue;
|
||||
fprintf(alternates, "%s\n", alternate);
|
||||
}
|
||||
|
||||
if (ferror(alternates)) {
|
||||
ret = error_errno(_("unable to write alternates file"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (commit_lock_file(&alternates_lock)) {
|
||||
ret = error_errno(_("unable to commit alternates file"));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reprepare the object database to activate alternates. */
|
||||
odb_reprepare(source->odb);
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
rollback_lock_file(&alternates_lock);
|
||||
strbuf_release(&line);
|
||||
strbuf_release(&path);
|
||||
return 0;
|
||||
strset_clear(&seen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void odb_source_files_prepare(struct odb_source *source,
|
||||
|
|
|
|||
17
odb/source.h
17
odb/source.h
|
|
@ -36,6 +36,15 @@ struct object_id;
|
|||
struct odb_stream;
|
||||
struct strvec;
|
||||
|
||||
struct odb_create_on_disk_options {
|
||||
/*
|
||||
* Alternates that shall be written into the newly created object
|
||||
* database. Whether or not this option can be handled is specific to
|
||||
* the backend.
|
||||
*/
|
||||
const struct strvec *alternates;
|
||||
};
|
||||
|
||||
/*
|
||||
* The source is the part of the object database that stores the actual
|
||||
* objects. It thus encapsulates the logic to read and write the specific
|
||||
|
|
@ -106,7 +115,8 @@ struct odb_source {
|
|||
* This callback may be NULL in case the source does not need any
|
||||
* on-disk setup.
|
||||
*/
|
||||
int (*create_on_disk)(struct odb_source *source);
|
||||
int (*create_on_disk)(struct odb_source *source,
|
||||
const struct odb_create_on_disk_options *opts);
|
||||
|
||||
/*
|
||||
* This callback is expected to prepare the source so that it becomes
|
||||
|
|
@ -356,11 +366,12 @@ static inline void odb_source_close(struct odb_source *source)
|
|||
* Create on-disk data structures that are required for this source to operate
|
||||
* correctly. Returns 0 on success, a negative error code otherwise.
|
||||
*/
|
||||
static inline int odb_source_create_on_disk(struct odb_source *source)
|
||||
static inline int odb_source_create_on_disk(struct odb_source *source,
|
||||
const struct odb_create_on_disk_options *opts)
|
||||
{
|
||||
if (!source->create_on_disk)
|
||||
return 0;
|
||||
return source->create_on_disk(source);
|
||||
return source->create_on_disk(source, opts);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
4
setup.c
4
setup.c
|
|
@ -2649,6 +2649,8 @@ static int create_default_files(struct repository *repo,
|
|||
|
||||
void create_object_database(struct repository *repo)
|
||||
{
|
||||
struct odb_create_on_disk_options opts = { 0 };
|
||||
|
||||
/*
|
||||
* Create the "objects" directory in the common directory. This is done
|
||||
* so that the repository can be discovered regardless of the backend
|
||||
|
|
@ -2668,7 +2670,7 @@ void create_object_database(struct repository *repo)
|
|||
|
||||
repo->objects = odb_new(repo, ODB_NEW_HONOR_ENV);
|
||||
|
||||
if (odb_source_create_on_disk(repo->objects->sources) < 0)
|
||||
if (odb_source_create_on_disk(repo->objects->sources, &opts) < 0)
|
||||
die(_("failed creating object database"));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue