Skip to content

Commit

Permalink
Move init_metadata to Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
glandium committed Nov 9, 2023
1 parent a1d07e3 commit 893ee09
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 131 deletions.
126 changes: 3 additions & 123 deletions src/cinnabar-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,15 +450,15 @@ void create_git_tree(const struct object_id *tree_id,
recurse_create_git_tree(tree_id, ref_tree, NULL, result, &git_tree_cache);
}

static void init_replace_map(void)
void init_replace_map(void)
{
the_repository->objects->replace_map =
xmalloc(sizeof(*the_repository->objects->replace_map));
oidmap_init(the_repository->objects->replace_map, 0);
the_repository->objects->replace_map_initialized = 1;
}

static void reset_replace_map(void)
void reset_replace_map(void)
{
oidmap_free(the_repository->objects->replace_map, 1);
FREE_AND_NULL(the_repository->objects->replace_map);
Expand All @@ -470,127 +470,7 @@ unsigned int replace_map_size(void)
return hashmap_get_size(&the_repository->objects->replace_map->map);
}

static int count_refs(const char *refname, const struct object_id *oid,
int flags, void *cb_dat) {
size_t *count = (size_t *)cb_dat;
(*count)++;
return 0;
}

static void init_metadata(struct commit *c)
{
struct commit_list *cl;
const char *msg, *body;
struct strbuf **flags, **f;
struct tree *tree;
struct tree_desc desc;
struct name_entry entry;
struct replace_object *replace;
size_t count = 0;

if (!c) {
oidcpy(&metadata_oid, null_oid());
oidcpy(&changesets_oid, null_oid());
oidcpy(&manifests_oid, null_oid());
oidcpy(&hg2git_oid, null_oid());
oidcpy(&git2hg_oid, null_oid());
oidcpy(&files_meta_oid, null_oid());
return;
}
oidcpy(&metadata_oid, &c->object.oid);
cl = c->parents;
if (!cl) die("Invalid metadata?");
oidcpy(&changesets_oid, &cl->item->object.oid);
cl = cl->next;
if (!cl) die("Invalid metadata?");
oidcpy(&manifests_oid, &cl->item->object.oid);
cl = cl->next;
if (!cl) die("Invalid metadata?");
oidcpy(&hg2git_oid, &cl->item->object.oid);
cl = cl->next;
if (!cl) die("Invalid metadata?");
oidcpy(&git2hg_oid, &cl->item->object.oid);
cl = cl->next;
if (!cl) die("Invalid metadata?");
oidcpy(&files_meta_oid, &cl->item->object.oid);

msg = repo_get_commit_buffer(the_repository, c, NULL);
body = strstr(msg, "\n\n") + 2;
flags = strbuf_split_str(body, ' ', -1);
for (f = flags; *f; f++) {
strbuf_trim(*f);
if (!strcmp("files-meta", (*f)->buf))
metadata_flags |= FILES_META;
else if (!strcmp("unified-manifests", (*f)->buf)) {
strbuf_list_free(flags);
repo_unuse_commit_buffer(the_repository, c, msg);
goto old;
} else if (!strcmp("unified-manifests-v2", (*f)->buf))
metadata_flags |= UNIFIED_MANIFESTS_v2;
else {
strbuf_list_free(flags);
repo_unuse_commit_buffer(the_repository, c, msg);
goto new;
}
}
strbuf_list_free(flags);
repo_unuse_commit_buffer(the_repository, c, msg);

if (!(metadata_flags & (FILES_META | UNIFIED_MANIFESTS_v2)))
goto old;

for_each_ref_in("refs/cinnabar/branches/", count_refs, &count);
if (count)
goto old;

reset_replace_map();
init_replace_map();

tree = repo_get_commit_tree(the_repository, c);
parse_tree(tree);
init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
struct object_id original_oid;
if (entry.pathlen != 40 ||
get_oid_hex(entry.path, &original_oid)) {
struct strbuf buf = STRBUF_INIT;
strbuf_add(&buf, entry.path, entry.pathlen);
warning(_("bad replace name: %s"), buf.buf);
strbuf_release(&buf);
continue;
}
if (oideq(&entry.oid, &original_oid)) {
warning(_("self-referencing graft: %s"),
oid_to_hex(&original_oid));
continue;
}
replace = xmalloc(sizeof(*replace));
oidcpy(&replace->original.oid, &original_oid);
oidcpy(&replace->replacement, &entry.oid);
if (oidmap_put(the_repository->objects->replace_map, replace))
die(_("duplicate replace: %s"),
oid_to_hex(&replace->original.oid));
}
if (the_repository->objects->replace_map->map.tablesize == 0) {
count = 0;
for_each_ref_in("refs/cinnabar/replace/", count_refs, &count);
if (count > 0)
goto old;
}
return;
old:
die("Metadata from git-cinnabar versions older than 0.5.0 is not "
"supported.\n"
"Please run `git cinnabar upgrade` with version 0.5.x first.");
new:
die("It looks like this repository was used with a newer version of "
"git-cinnabar. Cannot use this version.");
#if 0
upgrade:
die("Git-cinnabar metadata needs upgrade. "
"Please run `git cinnabar upgrade`.");
#endif
}
extern void init_metadata(struct commit *c);

void dump_ref_updates(void);

Expand Down
3 changes: 3 additions & 0 deletions src/cinnabar-helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,7 @@ int get_worktree_is_detached(const struct worktree *wr);

const struct object_id *get_worktree_head_oid(const struct worktree *wr);

void init_replace_map(void);
void reset_replace_map(void);

#endif
2 changes: 1 addition & 1 deletion src/graft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::progress::Progress;
use crate::store::{has_metadata, GeneratedGitChangesetMetadata, RawHgChangeset};

extern "C" {
fn replace_map_size() -> c_uint;
pub fn replace_map_size() -> c_uint;
}

pub fn grafted() -> bool {
Expand Down
2 changes: 1 addition & 1 deletion src/libgit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ pub struct commit(c_void);
pub struct commit_list(c_void);

extern "C" {
fn commit_oid(c: *const commit) -> *const object_id;
pub fn commit_oid(c: *const commit) -> *const object_id;

fn get_revision(revs: *mut rev_info) -> *const commit;

Expand Down
133 changes: 127 additions & 6 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::sync::Mutex;
use bit_vec::BitVec;
use bstr::{BStr, BString, ByteSlice};
use derive_more::Deref;
use either::Either;
use getset::{CopyGetters, Getters};
use hex_literal::hex;
use indexmap::IndexMap;
Expand All @@ -32,8 +33,8 @@ use crate::cinnabar::{
GitChangesetId, GitChangesetMetadataId, GitFileId, GitFileMetadataId, GitManifestId,
GitManifestTree, GitManifestTreeId,
};
use crate::git::{BlobId, CommitId, GitObjectId, TreeId, TreeIsh};
use crate::graft::{graft, grafted, GraftError};
use crate::git::{BlobId, CommitId, GitObjectId, GitOid, RecursedTreeEntry, TreeId, TreeIsh};
use crate::graft::{graft, grafted, replace_map_size, GraftError};
use crate::hg::{HgChangesetId, HgFileId, HgManifestId, HgObjectId};
use crate::hg_bundle::{
read_rev_chunk, rev_chunk, BundlePartInfo, BundleSpec, BundleWriter, RevChunkIter,
Expand All @@ -45,12 +46,13 @@ use crate::libcinnabar::{
strslice_mut,
};
use crate::libgit::{
changesets_oid, die, files_meta_oid, get_oid_blob, git2hg_oid, hg2git_oid, manifests_oid,
metadata_oid, object_id, strbuf, Commit, RawBlob, RawCommit, RawTree, RefTransaction,
changesets_oid, commit, commit_oid, die, files_meta_oid, for_each_ref_in, get_oid_blob,
git2hg_oid, hg2git_oid, manifests_oid, metadata_oid, object_id, strbuf, Commit, RawBlob,
RawCommit, RawTree, RefTransaction,
};
use crate::oid::ObjectId;
use crate::progress::{progress_enabled, Progress};
use crate::tree_util::{diff_by_path, Empty, ParseTree, RecurseTree};
use crate::tree_util::{diff_by_path, Empty, ParseTree, RecurseTree, WithPath};
use crate::util::{
FromBytes, ImmutBString, OsStrExt, RcExt, ReadExt, SliceExt, ToBoxed, Transpose,
};
Expand All @@ -65,10 +67,11 @@ pub const BROKEN_REF: &str = "refs/cinnabar/broken";
pub const NOTES_REF: &str = "refs/notes/cinnabar";

extern "C" {
pub static metadata_flags: c_int;
pub static mut metadata_flags: c_int;
}

pub const FILES_META: c_int = 0x1;
pub const UNIFIED_MANIFESTS_V2: c_int = 0x2;

pub fn has_metadata() -> bool {
unsafe { metadata_flags != 0 }
Expand Down Expand Up @@ -2034,9 +2037,127 @@ pub fn merge_metadata(git_url: Url, hg_url: Option<Url>, branch: Option<&[u8]>)
}

extern "C" {
fn init_replace_map();
fn reset_replace_map();
fn store_replace_map(result: *mut object_id);
}

fn old_metadata() {
die!(
"Metadata from git-cinnabar versions older than 0.5.0 is not supported.\n\
Please run `git cinnabar upgrade` with version 0.5.x first."
);
}

fn new_metadata() {
die!(
"It looks like this repository was used with a newer version of git-cinnabar. \
Cannot use this version."
);
}

#[allow(dead_code)]
fn need_upgrade() {
die!("Git-cinnabar metadata needs upgrade. Please run `git cinnabar upgrade` first.");
}

#[no_mangle]
pub unsafe extern "C" fn init_metadata(c: *const commit) {
let cid = if let Some(c) = c.as_ref() {
CommitId::from_unchecked(GitObjectId::from(commit_oid(c).as_ref().unwrap().clone()))
} else {
metadata_oid = object_id::default();
changesets_oid = object_id::default();
manifests_oid = object_id::default();
hg2git_oid = object_id::default();
git2hg_oid = object_id::default();
files_meta_oid = object_id::default();
return;
};
let c = RawCommit::read(cid).unwrap();
let c = c.parse().unwrap();
if !(5..=6).contains(&c.parents().len()) {
die!("Invalid metadata?");
}
for (cid, field) in Some(cid).iter().chain(c.parents()[..5].iter()).zip([
&mut metadata_oid,
&mut changesets_oid,
&mut manifests_oid,
&mut hg2git_oid,
&mut git2hg_oid,
&mut files_meta_oid,
]) {
*field = (*cid).into();
}
for flag in c.body().split(|&b| b == b' ') {
match flag {
b"files-meta" => {
metadata_flags |= FILES_META;
}
b"unified-manifests" => old_metadata(),
b"unified-manifests-v2" => {
metadata_flags |= UNIFIED_MANIFESTS_V2;
}
_ => new_metadata(),
}
eprintln!("{}", flag.as_bstr());
}
if metadata_flags != FILES_META | UNIFIED_MANIFESTS_V2 {
old_metadata();
}
let mut count = 0;
for_each_ref_in("refs/cinnabar/branches/", |_, _| -> Result<(), ()> {
count += 1;
Ok(())
})
.ok();
if count > 0 {
old_metadata();
}

reset_replace_map();

let tree = RawTree::read(c.tree()).unwrap();
let mut replaces = BTreeMap::new();
for (path, oid) in tree.into_iter().map(WithPath::unzip) {
match oid {
Either::Right(RecursedTreeEntry {
oid: GitOid::Commit(replace_with),
..
}) => {
if let Ok(original) = CommitId::from_bytes(&path) {
if original == replace_with {
warn!("self-referencing graft: {}", original);
} else {
replaces
.entry(original)
.and_modify(|_| die!("duplicate replace: {}", original))
.or_insert_with(|| replace_with);
}
} else {
warn!("bad replace name: {}", path.as_bstr());
}
}
_ => die!("Invalid metadata"),
}
}
init_replace_map();
for (original, replace_with) in replaces.into_iter() {
do_set_replace(&original.into(), &replace_with.into());
}
if replace_map_size() > 0 {
let mut count = 0;
for_each_ref_in("refs/cinnabar/replace/", |_, _| -> Result<(), ()> {
count += 1;
Ok(())
})
.ok();
if count > 0 {
old_metadata();
}
}
}

pub fn do_store_metadata() -> CommitId {
let mut hg2git_ = object_id::default();
let mut git2hg_ = object_id::default();
Expand Down

0 comments on commit 893ee09

Please sign in to comment.