Skip to content

Commit

Permalink
Move static notes trees to Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
glandium committed Nov 10, 2023
1 parent 8e2cba8 commit cf1dc03
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 45 deletions.
2 changes: 0 additions & 2 deletions src/cinnabar-helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
#include "cinnabar-fast-import.h"
#include "cinnabar-notes.h"

struct notes_tree git2hg, hg2git, files_meta;

struct object_id *commit_oid(struct commit *c) {
return &c->object.oid;
}
Expand Down
47 changes: 29 additions & 18 deletions src/libcinnabar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use std::ptr;
use crate::git::{CommitId, GitObjectId, TreeId};
use crate::hg::HgObjectId;
use crate::libgit::{
child_process, die, object_id, strbuf, FileMode, RawTree, FILES_META_OID, GIT2HG_OID,
HG2GIT_OID,
child_process, die, notes_tree, object_id, strbuf, FileMode, RawTree, FILES_META_OID,
GIT2HG_OID, HG2GIT_OID,
};
use crate::oid::{Abbrev, ObjectId};
use crate::store::{store_git_commit, MetadataFlags, METADATA_FLAGS};
Expand Down Expand Up @@ -98,15 +98,26 @@ impl From<hg_object_id> for HgObjectId {
#[allow(non_camel_case_types)]
#[repr(C)]
pub struct cinnabar_notes_tree {
root: *mut c_void,
// ...
current: notes_tree,
additions: notes_tree,
init_flags: c_int,
}

extern "C" {
pub static mut git2hg: git_notes_tree;
pub static mut hg2git: hg_notes_tree;
pub static mut files_meta: hg_notes_tree;
impl cinnabar_notes_tree {
const fn new() -> Self {
cinnabar_notes_tree {
current: notes_tree::new(),
additions: notes_tree::new(),
init_flags: 0,
}
}
}

pub static mut GIT2HG: git_notes_tree = git_notes_tree(cinnabar_notes_tree::new());
pub static mut HG2GIT: hg_notes_tree = hg_notes_tree(cinnabar_notes_tree::new());
pub static mut FILES_META: hg_notes_tree = hg_notes_tree(cinnabar_notes_tree::new());

extern "C" {
fn combine_notes_ignore(cur_oid: *mut object_id, new_oid: *const object_id) -> c_int;

fn cinnabar_init_notes(
Expand Down Expand Up @@ -168,11 +179,11 @@ unsafe fn ensure_notes(t: *mut cinnabar_notes_tree) {
if notes_initialized(t) == 0 {
let oid;
let mut flags = 0;
if ptr::eq(t, &git2hg.0) {
if ptr::eq(t, &GIT2HG.0) {
oid = GIT2HG_OID;
} else if ptr::eq(t, &hg2git.0) {
} else if ptr::eq(t, &HG2GIT.0) {
oid = HG2GIT_OID;
} else if ptr::eq(t, &files_meta.0) {
} else if ptr::eq(t, &FILES_META.0) {
oid = FILES_META_OID;
if METADATA_FLAGS.contains(MetadataFlags::FILES_META) {
flags = NOTES_INIT_EMPTY;
Expand Down Expand Up @@ -210,8 +221,8 @@ fn for_each_note_in<F: FnMut(GitObjectId, GitObjectId)>(notes: &mut cinnabar_not

#[no_mangle]
pub unsafe extern "C" fn resolve_hg2git(oid: *const hg_object_id) -> *const object_id {
ensure_notes(&mut hg2git.0);
get_note_hg(&mut hg2git.0, oid)
ensure_notes(&mut HG2GIT.0);
get_note_hg(&mut HG2GIT.0, oid)
}

unsafe fn get_note_hg(
Expand All @@ -226,8 +237,8 @@ unsafe fn get_note_hg(

#[no_mangle]
pub unsafe extern "C" fn get_files_meta(oid: *const hg_object_id) -> *const object_id {
ensure_notes(&mut files_meta.0);
get_note_hg(&mut files_meta.0, oid)
ensure_notes(&mut FILES_META.0);
get_note_hg(&mut FILES_META.0, oid)
}

unsafe fn add_note_hg(
Expand All @@ -244,15 +255,15 @@ unsafe fn add_note_hg(

#[no_mangle]
pub unsafe extern "C" fn add_hg2git(oid: *const hg_object_id, note_oid: *const object_id) -> c_int {
add_note_hg(&mut hg2git.0, oid, note_oid)
add_note_hg(&mut HG2GIT.0, oid, note_oid)
}

#[no_mangle]
pub unsafe extern "C" fn add_files_meta(
oid: *const hg_object_id,
note_oid: *const object_id,
) -> c_int {
add_note_hg(&mut files_meta.0, oid, note_oid)
add_note_hg(&mut FILES_META.0, oid, note_oid)
}

pub unsafe fn store_metadata_notes(
Expand All @@ -262,7 +273,7 @@ pub unsafe fn store_metadata_notes(
let mut result = object_id::default();
let mut tree = object_id::default();
if notes_dirty(notes) != 0 {
let mode = if ptr::eq(notes, &hg2git.0) {
let mode = if ptr::eq(notes, &HG2GIT.0) {
FileMode::GITLINK
} else {
FileMode::REGULAR | FileMode::RW
Expand Down
34 changes: 34 additions & 0 deletions src/libgit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::ffi::{c_void, CStr, CString, OsStr, OsString};
use std::io::{self, Write};
use std::num::ParseIntError;
use std::os::raw::{c_char, c_int, c_long, c_uint, c_ulong, c_ushort};
use std::ptr;
use std::str::FromStr;
use std::sync::RwLock;
use std::{fmt, mem};
Expand Down Expand Up @@ -1240,3 +1241,36 @@ pub fn reachable_subset(
},
}
}

#[allow(non_camel_case_types)]
#[repr(C)]
pub struct notes_tree {
root: *mut c_void,
first_non_note: *mut c_void,
prev_non_note: *mut c_void,
r#ref: *const c_char,
update_ref: *const c_char,
combine_notes:
unsafe extern "C" fn(cur_oid: *mut object_id, new_oid: *const object_id) -> c_int,
initialized: c_int,
dirty: c_int,
}

extern "C" {
fn combine_notes_ignore(cur_oid: *mut object_id, new_oid: *const object_id) -> c_int;
}

impl notes_tree {
pub const fn new() -> Self {
notes_tree {
root: ptr::null_mut(),
first_non_note: ptr::null_mut(),
prev_non_note: ptr::null_mut(),
r#ref: ptr::null(),
update_ref: ptr::null(),
combine_notes: combine_notes_ignore,
initialized: 0,
dirty: 0,
}
}
}
16 changes: 8 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ use hg_connect::{get_bundle, get_clonebundle_url, get_connection, get_store_bund
use indexmap::IndexSet;
use itertools::EitherOrBoth::{Both, Left, Right};
use itertools::{EitherOrBoth, Itertools};
use libcinnabar::{files_meta, git2hg, git_notes_tree, hg2git};
use libcinnabar::{FILES_META, GIT2HG, git_notes_tree, HG2GIT};
use libgit::{
commit, config_get_value, die, diff_tree_with_copies, for_each_ref_in, for_each_remote,
get_oid_committish, get_unique_abbrev, lookup_commit, lookup_replace_commit, object_id,
Expand Down Expand Up @@ -290,7 +290,7 @@ pub fn prepare_arg(arg: OsString) -> Vec<u16> {

fn do_one_hg2git(sha1: Abbrev<HgChangesetId>) -> String {
format!("{}", unsafe {
hg2git.get_note_abbrev(sha1).unwrap_or(GitObjectId::NULL)
HG2GIT.get_note_abbrev(sha1).unwrap_or(GitObjectId::NULL)
})
}

Expand Down Expand Up @@ -353,7 +353,7 @@ where

fn do_data_changeset(rev: Abbrev<HgChangesetId>) -> Result<(), String> {
unsafe {
let commit_id = hg2git
let commit_id = HG2GIT
.get_note_abbrev(rev)
.ok_or_else(|| format!("Unknown changeset id: {}", rev))?;
let changeset = RawHgChangeset::read(GitChangesetId::from_unchecked(
Expand All @@ -366,7 +366,7 @@ fn do_data_changeset(rev: Abbrev<HgChangesetId>) -> Result<(), String> {

fn do_data_manifest(rev: Abbrev<HgManifestId>) -> Result<(), String> {
unsafe {
let commit_id = hg2git
let commit_id = HG2GIT
.get_note_abbrev(rev)
.ok_or_else(|| format!("Unknown manifest id: {}", rev))?;
let manifest = RawHgManifest::read(GitManifestId::from_unchecked(
Expand Down Expand Up @@ -1779,11 +1779,11 @@ fn do_setup() -> Result<(), String> {
fn do_data_file(rev: Abbrev<HgFileId>) -> Result<(), String> {
unsafe {
let mut stdout = stdout();
let blob_id = hg2git
let blob_id = HG2GIT
.get_note_abbrev(rev)
.ok_or_else(|| format!("Unknown file id: {}", rev))?;
let file_id = GitFileId::from_unchecked(BlobId::from_unchecked(blob_id));
let metadata_id = files_meta
let metadata_id = FILES_META
.get_note_abbrev(rev)
.map(|oid| GitFileMetadataId::from_unchecked(BlobId::from_unchecked(oid)));
let file = RawHgFile::read(file_id, metadata_id).unwrap();
Expand Down Expand Up @@ -3124,7 +3124,7 @@ fn do_fsck_full(
}

if full_fsck && !broken.get() {
unsafe { &mut hg2git }.for_each(|h, _| {
unsafe { &mut HG2GIT }.for_each(|h, _| {
if seen_changesets.contains(&HgChangesetId::from_unchecked(h))
|| seen_manifests.contains(&HgManifestId::from_unchecked(h))
|| seen_files.contains(&HgFileId::from_unchecked(h))
Expand All @@ -3139,7 +3139,7 @@ fn do_fsck_full(
do_set(SetWhat::File, h, GitObjectId::NULL);
do_set(SetWhat::FileMeta, h, GitObjectId::NULL);
});
unsafe { &mut git2hg }.for_each(|g, _| {
unsafe { &mut GIT2HG }.for_each(|g, _| {
// TODO: this is gross.
let cid = GitChangesetId::from_unchecked(CommitId::from_unchecked(g));
if seen_git2hg.contains(&cid) {
Expand Down
34 changes: 17 additions & 17 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use crate::hg_bundle::{
use crate::hg_connect_http::HttpRequest;
use crate::hg_data::{hash_data, GitAuthorship, HgAuthorship, HgCommitter};
use crate::libcinnabar::{
files_meta, git2hg, git_notes_tree, hg2git, hg_notes_tree, strslice, strslice_mut,
FILES_META, GIT2HG, git_notes_tree, HG2GIT, hg_notes_tree, strslice, strslice_mut,
};
use crate::libgit::{
commit, commit_oid, die, for_each_ref_in, get_oid_blob, object_id, strbuf, Commit, RawBlob,
Expand Down Expand Up @@ -85,7 +85,7 @@ macro_rules! hg2git {
impl $h {
pub fn to_git(self) -> Option<$g> {
unsafe {
hg2git
HG2GIT
.get_note(self.into())
.map(|o| $g::from_raw_bytes(o.as_raw_bytes()).unwrap())
}
Expand Down Expand Up @@ -114,7 +114,7 @@ pub struct RawGitChangesetMetadata(RawBlob);

impl RawGitChangesetMetadata {
pub fn read(changeset_id: GitChangesetId) -> Option<Self> {
Self::read_from_notes_tree(unsafe { &mut git2hg }, changeset_id)
Self::read_from_notes_tree(unsafe { &mut GIT2HG }, changeset_id)
}

pub fn read_from_notes_tree(
Expand Down Expand Up @@ -691,7 +691,7 @@ impl RawHgFile {
if oid == Self::EMPTY_OID {
Some(Self(vec![].into()))
} else {
let metadata = unsafe { files_meta.get_note(oid.into()) }
let metadata = unsafe { FILES_META.get_note(oid.into()) }
.map(BlobId::from_unchecked)
.map(GitFileMetadataId::from_unchecked);
Self::read(oid.to_git().unwrap(), metadata)
Expand Down Expand Up @@ -1181,10 +1181,10 @@ pub fn do_set(what: SetWhat, hg_id: HgObjectId, git_id: GitObjectId) {
match what {
SetWhat::Changeset => {
if git_id.is_null() {
unsafe { &mut hg2git }.remove_note(hg_id);
unsafe { &mut HG2GIT }.remove_note(hg_id);
} else if let Ok(ref mut commit) = CommitId::try_from(git_id) {
handle_changeset_conflict(HgChangesetId::from_unchecked(hg_id), commit);
unsafe { &mut hg2git }.add_note(hg_id, (*commit).into());
unsafe { &mut HG2GIT }.add_note(hg_id, (*commit).into());
} else {
die!("Invalid object");
}
Expand All @@ -1194,13 +1194,13 @@ pub fn do_set(what: SetWhat, hg_id: HgObjectId, git_id: GitObjectId) {
if let Some(cid) = csid.to_git() {
if git_id.is_null() {
unsafe {
git2hg.remove_note(cid.into());
GIT2HG.remove_note(cid.into());
}
} else if BlobId::try_from(git_id).is_err() {
die!("Invalid object");
} else {
unsafe {
git2hg.add_note(cid.into(), git_id);
GIT2HG.add_note(cid.into(), git_id);
}
}
} else if !git_id.is_null() {
Expand All @@ -1216,13 +1216,13 @@ pub fn do_set(what: SetWhat, hg_id: HgObjectId, git_id: GitObjectId) {
git_id,
)));
}
set::<CommitId>(unsafe { &mut hg2git }, hg_id, git_id);
set::<CommitId>(unsafe { &mut HG2GIT }, hg_id, git_id);
}
SetWhat::File => {
set::<BlobId>(unsafe { &mut hg2git }, hg_id, git_id);
set::<BlobId>(unsafe { &mut HG2GIT }, hg_id, git_id);
}
SetWhat::FileMeta => {
set::<BlobId>(unsafe { &mut files_meta }, hg_id, git_id);
set::<BlobId>(unsafe { &mut FILES_META }, hg_id, git_id);
}
}
}
Expand Down Expand Up @@ -2174,9 +2174,9 @@ pub unsafe extern "C" fn init_metadata(c: *const commit) {

#[no_mangle]
pub unsafe extern "C" fn done_metadata() {
git2hg.done();
hg2git.done();
files_meta.done();
GIT2HG.done();
HG2GIT.done();
FILES_META.done();
}

pub fn do_store_metadata() -> CommitId {
Expand All @@ -2188,9 +2188,9 @@ pub fn do_store_metadata() -> CommitId {
let mut tree = object_id::default();
let mut previous = None;
unsafe {
hg2git_ = hg2git.store(HG2GIT_OID);
git2hg_ = git2hg.store(GIT2HG_OID);
files_meta_ = files_meta.store(FILES_META_OID);
hg2git_ = HG2GIT.store(HG2GIT_OID);
git2hg_ = GIT2HG.store(GIT2HG_OID);
files_meta_ = FILES_META.store(FILES_META_OID);
manifests = store_manifests_metadata();
changesets = store_changesets_metadata();
if !METADATA_OID.is_null() {
Expand Down

0 comments on commit cf1dc03

Please sign in to comment.