Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Git support optional in the lib crate #3854

Merged
merged 2 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ jobs:
env:
RUST_BACKTRACE: 1

build-no-git:
name: Build jj-lib without Git support
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29

- name: Install Rust
uses: dtolnay/rust-toolchain@1482605bfc5719782e1267fd0c0cc350fe7646b8
with:
toolchain: 1.76
- name: Build
run: cargo build -p jj-lib --no-default-features --verbose

check-protos:
name: Check protos
runs-on: ubuntu-latest
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
modifier. Surround with parentheses if it should be parsed as string/file
pattern.

* Dropped support for automatic upgrade of repo formats used by versions before
0.12.0.

### Deprecations

### New features
Expand Down
7 changes: 4 additions & 3 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ config = { workspace = true }
digest = { workspace = true }
either = { workspace = true }
futures = { workspace = true }
git2 = { workspace = true }
gix = { workspace = true }
git2 = { workspace = true, optional = true }
gix = { workspace = true, optional = true }
glob = { workspace = true }
hex = { workspace = true }
ignore = { workspace = true }
Expand Down Expand Up @@ -91,7 +91,8 @@ testutils = { workspace = true }
tokio = { workspace = true, features = ["full"] }

[features]
default = []
default = ["git"]
git = ["dep:git2", "dep:gix"]
vendored-openssl = ["git2/vendored-openssl"]
watchman = ["dep:tokio", "dep:watchman_client"]
testing = []
2 changes: 2 additions & 0 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ pub mod fileset;
mod fileset_parser;
pub mod fmt_util;
pub mod fsmonitor;
#[cfg(feature = "git")]
pub mod git;
#[cfg(feature = "git")]
pub mod git_backend;
pub mod gitignore;
pub mod gpg_signing;
Expand Down
63 changes: 14 additions & 49 deletions lib/src/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
use std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Formatter};
use std::io::ErrorKind;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::sync::Arc;
Expand All @@ -38,7 +37,6 @@ use crate::commit_builder::CommitBuilder;
use crate::default_index::{DefaultIndexStore, DefaultMutableIndex};
use crate::default_submodule_store::DefaultSubmoduleStore;
use crate::file_util::{IoResultExt as _, PathError};
use crate::git_backend::GitBackend;
use crate::index::{ChangeIdIndex, Index, IndexStore, MutableIndex, ReadonlyIndex};
use crate::local_backend::LocalBackend;
use crate::object_id::{HexPrefix, ObjectId, PrefixResolution};
Expand Down Expand Up @@ -379,9 +377,14 @@ impl Default for StoreFactories {
LocalBackend::name(),
Box::new(|_settings, store_path| Ok(Box::new(LocalBackend::load(store_path)))),
);
#[cfg(feature = "git")]
factories.add_backend(
GitBackend::name(),
Box::new(|settings, store_path| Ok(Box::new(GitBackend::load(settings, store_path)?))),
crate::git_backend::GitBackend::name(),
Box::new(|settings, store_path| {
Ok(Box::new(crate::git_backend::GitBackend::load(
settings, store_path,
)?))
}),
);
#[cfg(feature = "testing")]
factories.add_backend(
Expand Down Expand Up @@ -478,19 +481,7 @@ impl StoreFactories {
settings: &UserSettings,
store_path: &Path,
) -> Result<Box<dyn Backend>, StoreLoadError> {
// For compatibility with existing repos. TODO: Delete in 0.8+.
if store_path.join("backend").is_file() {
fs::rename(store_path.join("backend"), store_path.join("type"))
.expect("Failed to rename 'backend' file to 'type'");
}
// For compatibility with existing repos. TODO: Delete default in 0.8+.
let backend_type = read_store_type_compat("commit", store_path.join("type"), || {
if store_path.join("git_target").is_file() {
GitBackend::name()
} else {
LocalBackend::name()
}
})?;
let backend_type = read_store_type("commit", store_path.join("type"))?;
let backend_factory = self.backend_factories.get(&backend_type).ok_or_else(|| {
StoreLoadError::UnsupportedType {
store: "commit",
Expand All @@ -509,9 +500,7 @@ impl StoreFactories {
settings: &UserSettings,
store_path: &Path,
) -> Result<Box<dyn OpStore>, StoreLoadError> {
// For compatibility with existing repos. TODO: Delete default in 0.8+.
let op_store_type =
read_store_type_compat("operation", store_path.join("type"), SimpleOpStore::name)?;
let op_store_type = read_store_type("operation", store_path.join("type"))?;
let op_store_factory = self.op_store_factories.get(&op_store_type).ok_or_else(|| {
StoreLoadError::UnsupportedType {
store: "operation",
Expand All @@ -531,12 +520,7 @@ impl StoreFactories {
settings: &UserSettings,
store_path: &Path,
) -> Result<Box<dyn OpHeadsStore>, StoreLoadError> {
// For compatibility with existing repos. TODO: Delete default in 0.8+.
let op_heads_store_type = read_store_type_compat(
"operation heads",
store_path.join("type"),
SimpleOpHeadsStore::name,
)?;
let op_heads_store_type = read_store_type("operation heads", store_path.join("type"))?;
let op_heads_store_factory = self
.op_heads_store_factories
.get(&op_heads_store_type)
Expand All @@ -556,9 +540,7 @@ impl StoreFactories {
settings: &UserSettings,
store_path: &Path,
) -> Result<Box<dyn IndexStore>, StoreLoadError> {
// For compatibility with existing repos. TODO: Delete default in 0.9+
let index_store_type =
read_store_type_compat("index", store_path.join("type"), DefaultIndexStore::name)?;
let index_store_type = read_store_type("index", store_path.join("type"))?;
let index_store_factory = self
.index_store_factories
.get(&index_store_type)
Expand All @@ -579,13 +561,7 @@ impl StoreFactories {
settings: &UserSettings,
store_path: &Path,
) -> Result<Box<dyn SubmoduleStore>, StoreLoadError> {
// For compatibility with repos without repo/submodule_store.
// TODO Delete default in TBD version
let submodule_store_type = read_store_type_compat(
"submodule_store",
store_path.join("type"),
DefaultSubmoduleStore::name,
)?;
let submodule_store_type = read_store_type("submodule_store", store_path.join("type"))?;
let submodule_store_factory = self
.submodule_store_factories
.get(&submodule_store_type)
Expand All @@ -598,23 +574,12 @@ impl StoreFactories {
}
}

pub fn read_store_type_compat(
pub fn read_store_type(
store: &'static str,
path: impl AsRef<Path>,
default: impl FnOnce() -> &'static str,
) -> Result<String, StoreLoadError> {
let path = path.as_ref();
let read_or_write_default = || match fs::read_to_string(path) {
Ok(content) => Ok(content),
Err(err) if err.kind() == ErrorKind::NotFound => {
let default_type = default();
fs::create_dir(path.parent().unwrap()).ok();
fs::write(path, default_type)?;
Ok(default_type.to_owned())
}
Err(err) => Err(err),
};
read_or_write_default()
fs::read_to_string(path)
.context(path)
.map_err(|source| StoreLoadError::ReadError { store, source })
}
Expand Down
17 changes: 14 additions & 3 deletions lib/src/revset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub use crate::revset_parser::{
};
use crate::store::Store;
use crate::str_util::StringPattern;
use crate::{dsl_util, git, revset_parser};
use crate::{dsl_util, revset_parser};

/// Error occurred during symbol resolution.
#[derive(Debug, Error)]
Expand Down Expand Up @@ -1313,7 +1313,8 @@ pub fn walk_revs<'index>(
fn resolve_remote_branch(repo: &dyn Repo, name: &str, remote: &str) -> Option<Vec<CommitId>> {
let view = repo.view();
let target = match (name, remote) {
("HEAD", git::REMOTE_NAME_FOR_LOCAL_GIT_REPO) => view.git_head(),
#[cfg(feature = "git")]
("HEAD", crate::git::REMOTE_NAME_FOR_LOCAL_GIT_REPO) => view.git_head(),
(name, remote) => &view.get_remote_branch(name, remote).target,
};
target
Expand Down Expand Up @@ -1605,7 +1606,17 @@ fn resolve_commit_ref(
let commit_ids = repo
.view()
.remote_branches_matching(branch_pattern, remote_pattern)
.filter(|&((_, remote_name), _)| remote_name != git::REMOTE_NAME_FOR_LOCAL_GIT_REPO)
.filter(|&((_, remote_name), _)| {
#[cfg(feature = "git")]
{
remote_name != crate::git::REMOTE_NAME_FOR_LOCAL_GIT_REPO
}
#[cfg(not(feature = "git"))]
{
let _ = remote_name;
true
}
})
.flat_map(|(_, remote_ref)| remote_ref.target.added_ids())
.cloned()
.collect();
Expand Down
27 changes: 19 additions & 8 deletions lib/src/simple_op_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use crate::op_store::{
OpStore, OpStoreError, OpStoreResult, Operation, OperationId, OperationMetadata, RefTarget,
RemoteRef, RemoteRefState, RemoteView, View, ViewId, WorkspaceId,
};
use crate::{dag_walk, git, op_store};
use crate::{dag_walk, op_store};

// BLAKE2b-512 hash length in bytes
const OPERATION_ID_LENGTH: usize = 64;
Expand Down Expand Up @@ -528,8 +528,11 @@ fn branch_views_from_proto_legacy(
// than deleted but yet-to-be-pushed local branch. Alternatively, we could read
// git.auto-local-branch setting here, but that wouldn't always work since the
// setting could be toggled after the branch got merged.
#[cfg(feature = "git")]
let is_git_tracking =
remote_branch.remote_name == git::REMOTE_NAME_FOR_LOCAL_GIT_REPO;
remote_branch.remote_name == crate::git::REMOTE_NAME_FOR_LOCAL_GIT_REPO;
#[cfg(not(feature = "git"))]
let is_git_tracking = false;
let default_state = if is_git_tracking || local_target.is_present() {
RemoteRefState::Tracking
} else {
Expand Down Expand Up @@ -578,13 +581,21 @@ fn migrate_git_refs_to_remote(view: &mut View) {
git_view.branches.insert(name.to_owned(), remote_ref);
}
}
view.remote_views
.insert(git::REMOTE_NAME_FOR_LOCAL_GIT_REPO.to_owned(), git_view);
#[cfg(feature = "git")]
{
view.remote_views.insert(
crate::git::REMOTE_NAME_FOR_LOCAL_GIT_REPO.to_owned(),
git_view,
);

// jj < 0.9 might have imported refs from remote named "git"
let reserved_git_ref_prefix = format!("refs/remotes/{}/", git::REMOTE_NAME_FOR_LOCAL_GIT_REPO);
view.git_refs
.retain(|name, _| !name.starts_with(&reserved_git_ref_prefix));
// jj < 0.9 might have imported refs from remote named "git"
let reserved_git_ref_prefix = format!(
"refs/remotes/{}/",
crate::git::REMOTE_NAME_FOR_LOCAL_GIT_REPO
);
view.git_refs
.retain(|name, _| !name.starts_with(&reserved_git_ref_prefix));
}
}

fn ref_target_to_proto(value: &RefTarget) -> Option<crate::protos::op_store::RefTarget> {
Expand Down
Loading
Loading