diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c71a2f93b..f5bfa59fb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: rust_version: stable - build: linux-msrv os: ubuntu-latest - rust_version: 1.58 + rust_version: "1.60" - build: macos os: macos-latest rust_version: stable diff --git a/Cargo.lock b/Cargo.lock index 3bb0217c9..1c2b4e2fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" + [[package]] name = "assert_cmd" version = "2.0.4" @@ -774,7 +780,7 @@ dependencies = [ "pest", "pest_derive", "protobuf", - "protobuf-codegen-pure", + "protobuf-codegen", "rand", "regex", "serde_json", @@ -1155,30 +1161,54 @@ dependencies = [ [[package]] name = "protobuf" -version = "2.27.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96" +checksum = "430ff91293021cc9369e04edced9594c9c7a03760e62afcf98b0f8ad99a56ef7" dependencies = [ "bytes", + "once_cell", + "protobuf-support", + "thiserror", ] [[package]] name = "protobuf-codegen" -version = "2.27.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aec1632b7c8f2e620343439a7dfd1f3c47b18906c4be58982079911482b5d707" +checksum = "f9248f242f2b2915e050852c56058dffe2ea9d71fba735d8eb33be78973b71cd" dependencies = [ + "anyhow", + "once_cell", "protobuf", + "protobuf-parse", + "regex", + "tempfile", + "thiserror", ] [[package]] -name = "protobuf-codegen-pure" -version = "2.27.1" +name = "protobuf-parse" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f8122fdb18e55190c796b088a16bdb70cd7acdcd48f7a8b796b58c62e532cc6" +checksum = "a7aa0f9769c554c90cb1b28592f7efe03ad2540de046dfa21d89155776c27c29" dependencies = [ + "anyhow", + "indexmap", + "log", "protobuf", - "protobuf-codegen", + "protobuf-support", + "tempfile", + "thiserror", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9553cd16fcb53a9b33da0735313393ba2697d090ae9af4a96f160992513ce8cb" +dependencies = [ + "thiserror", ] [[package]] @@ -1774,6 +1804,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "which" +version = "4.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +dependencies = [ + "either", + "lazy_static", + "libc", +] + [[package]] name = "whoami" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index 0d97a341a..62d6b1154 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "jujutsu" version = "0.4.0" authors = ["Martin von Zweigbergk "] edition = "2021" -rust-version = "1.58" # Remember to update CI +rust-version = "1.60" # Remember to update CI license = "Apache-2.0" description = "Jujutsu (an experimental VCS)" homepage = "https://github.com/martinvonz/jj" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index d8624f050..419b3f580 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -3,7 +3,7 @@ name = "jujutsu-lib" version = "0.4.0" authors = ["Martin von Zweigbergk "] edition = "2021" -rust-version = "1.57" +rust-version = "1.60" license = "Apache-2.0" description = "Library for Jujutsu (an experimental VCS)" homepage = "https://github.com/martinvonz/jj" @@ -14,7 +14,7 @@ readme = "../README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] -protobuf-codegen-pure = "2.27.1" +protobuf-codegen = "3.0.1" version_check = "0.9.4" [dependencies] @@ -30,7 +30,7 @@ itertools = "0.10.3" maplit = "1.0.2" pest = "2.1.3" pest_derive = "2.1.0" -protobuf = { version = "2.27.1", features = ["with-bytes"] } +protobuf = { version = "3.0.1", features = ["with-bytes"] } rand = "0.8.5" regex = "1.5.5" serde_json = "1.0.81" diff --git a/lib/build.rs b/lib/build.rs index 743214ba0..8a0278cda 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -12,13 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -extern crate protobuf_codegen_pure; +extern crate protobuf_codegen; extern crate version_check; use std::path::Path; -use protobuf_codegen_pure::Customize; - fn main() { let out_dir = format!("{}/protos", std::env::var("OUT_DIR").unwrap()); @@ -32,14 +30,12 @@ fn main() { "protos/store.proto", "protos/working_copy.proto", ]; - protobuf_codegen_pure::Codegen::new() - .customize(Customize { - gen_mod_rs: Some(true), - ..Default::default() - }) + protobuf_codegen::Codegen::new() + .pure() .out_dir(out_dir) .inputs(input) .include("protos") + .cargo_out_dir("protos") .run() .expect("protoc"); println!("cargo:rerun-if-changed=build.rs"); diff --git a/lib/protos/op_store.proto b/lib/protos/op_store.proto index 1a7d2c2a6..fe364da61 100644 --- a/lib/protos/op_store.proto +++ b/lib/protos/op_store.proto @@ -14,6 +14,8 @@ syntax = "proto3"; +package op_store; + message RefConflict { repeated bytes removes = 1; repeated bytes adds = 2; diff --git a/lib/protos/store.proto b/lib/protos/store.proto index 134624385..29c8df99b 100644 --- a/lib/protos/store.proto +++ b/lib/protos/store.proto @@ -14,6 +14,8 @@ syntax = "proto3"; +package store; + message TreeValue { message NormalFile { bytes id = 1; diff --git a/lib/protos/working_copy.proto b/lib/protos/working_copy.proto index ab4cc8df3..29e7e33f9 100644 --- a/lib/protos/working_copy.proto +++ b/lib/protos/working_copy.proto @@ -14,6 +14,8 @@ syntax = "proto3"; +package working_copy; + enum FileType { Normal = 0; Symlink = 1; diff --git a/lib/src/local_backend.rs b/lib/src/local_backend.rs index 4da980cab..50b0e773a 100644 --- a/lib/src/local_backend.rs +++ b/lib/src/local_backend.rs @@ -19,7 +19,7 @@ use std::io::{ErrorKind, Read, Write}; use std::path::PathBuf; use blake2::{Blake2b512, Digest}; -use protobuf::{Message, ProtobufError}; +use protobuf::{Message, MessageField}; use tempfile::{NamedTempFile, PersistError}; use crate::backend::{ @@ -42,8 +42,8 @@ impl From for BackendError { } } -impl From for BackendError { - fn from(err: ProtobufError) -> Self { +impl From for BackendError { + fn from(err: protobuf::Error) -> Self { BackendError::Other(err.to_string()) } } @@ -247,12 +247,12 @@ pub fn commit_to_proto(commit: &Commit) -> crate::protos::store::Commit { for predecessor in &commit.predecessors { proto.predecessors.push(predecessor.to_bytes()); } - proto.set_root_tree(commit.root_tree.to_bytes()); - proto.set_change_id(commit.change_id.to_bytes()); - proto.set_description(commit.description.clone()); - proto.set_author(signature_to_proto(&commit.author)); - proto.set_committer(signature_to_proto(&commit.committer)); - proto.set_is_open(commit.is_open); + proto.root_tree = commit.root_tree.to_bytes(); + proto.change_id = commit.change_id.to_bytes(); + proto.description = commit.description.clone(); + proto.author = MessageField::some(signature_to_proto(&commit.author)); + proto.committer = MessageField::some(signature_to_proto(&commit.committer)); + proto.is_open = commit.is_open; proto } @@ -272,8 +272,8 @@ fn commit_from_proto(proto: &crate::protos::store::Commit) -> Commit { root_tree, change_id, description: proto.description.clone(), - author: signature_from_proto(proto.author.get_ref()), - committer: signature_from_proto(proto.committer.get_ref()), + author: signature_from_proto(&proto.author), + committer: signature_from_proto(&proto.committer), is_open: proto.is_open, } } @@ -281,9 +281,9 @@ fn commit_from_proto(proto: &crate::protos::store::Commit) -> Commit { fn tree_to_proto(tree: &Tree) -> crate::protos::store::Tree { let mut proto = crate::protos::store::Tree::new(); for entry in tree.entries() { - let mut proto_entry = crate::protos::store::Tree_Entry::new(); - proto_entry.set_name(entry.name().string()); - proto_entry.set_value(tree_value_to_proto(entry.value())); + let mut proto_entry = crate::protos::store::tree::Entry::new(); + proto_entry.name = entry.name().string(); + proto_entry.value = MessageField::some(tree_value_to_proto(entry.value())); proto.entries.push(proto_entry); } proto @@ -302,9 +302,9 @@ fn tree_value_to_proto(value: &TreeValue) -> crate::protos::store::TreeValue { let mut proto = crate::protos::store::TreeValue::new(); match value { TreeValue::Normal { id, executable } => { - let mut file = crate::protos::store::TreeValue_NormalFile::new(); - file.set_id(id.to_bytes()); - file.set_executable(*executable); + let mut file = crate::protos::store::tree_value::NormalFile::new(); + file.id = id.to_bytes(); + file.executable = *executable; proto.set_normal_file(file); } TreeValue::Symlink(id) => { @@ -325,37 +325,37 @@ fn tree_value_to_proto(value: &TreeValue) -> crate::protos::store::TreeValue { fn tree_value_from_proto(proto: &crate::protos::store::TreeValue) -> TreeValue { match proto.value.as_ref().unwrap() { - crate::protos::store::TreeValue_oneof_value::tree_id(id) => { + crate::protos::store::tree_value::Value::TreeId(id) => { TreeValue::Tree(TreeId::new(id.clone())) } - crate::protos::store::TreeValue_oneof_value::normal_file( - crate::protos::store::TreeValue_NormalFile { id, executable, .. }, + crate::protos::store::tree_value::Value::NormalFile( + crate::protos::store::tree_value::NormalFile { id, executable, .. }, ) => TreeValue::Normal { id: FileId::new(id.clone()), executable: *executable, }, - crate::protos::store::TreeValue_oneof_value::symlink_id(id) => { + crate::protos::store::tree_value::Value::SymlinkId(id) => { TreeValue::Symlink(SymlinkId::new(id.clone())) } - crate::protos::store::TreeValue_oneof_value::conflict_id(id) => { + crate::protos::store::tree_value::Value::ConflictId(id) => { TreeValue::Conflict(ConflictId::new(id.clone())) } } } -fn signature_to_proto(signature: &Signature) -> crate::protos::store::Commit_Signature { - let mut proto = crate::protos::store::Commit_Signature::new(); - proto.set_name(signature.name.clone()); - proto.set_email(signature.email.clone()); - let mut timestamp_proto = crate::protos::store::Commit_Timestamp::new(); - timestamp_proto.set_millis_since_epoch(signature.timestamp.timestamp.0); - timestamp_proto.set_tz_offset(signature.timestamp.tz_offset); - proto.set_timestamp(timestamp_proto); +fn signature_to_proto(signature: &Signature) -> crate::protos::store::commit::Signature { + let mut proto = crate::protos::store::commit::Signature::new(); + proto.name = signature.name.clone(); + proto.email = signature.email.clone(); + let mut timestamp_proto = crate::protos::store::commit::Timestamp::new(); + timestamp_proto.millis_since_epoch = signature.timestamp.timestamp.0; + timestamp_proto.tz_offset = signature.timestamp.tz_offset; + proto.timestamp = MessageField::some(timestamp_proto); proto } -fn signature_from_proto(proto: &crate::protos::store::Commit_Signature) -> Signature { - let timestamp = proto.get_timestamp(); +fn signature_from_proto(proto: &crate::protos::store::commit::Signature) -> Signature { + let timestamp = &proto.timestamp; Signature { name: proto.name.clone(), email: proto.email.clone(), @@ -388,14 +388,14 @@ fn conflict_from_proto(proto: &crate::protos::store::Conflict) -> Conflict { conflict } -fn conflict_part_from_proto(proto: &crate::protos::store::Conflict_Part) -> ConflictPart { +fn conflict_part_from_proto(proto: &crate::protos::store::conflict::Part) -> ConflictPart { ConflictPart { value: tree_value_from_proto(proto.content.as_ref().unwrap()), } } -fn conflict_part_to_proto(part: &ConflictPart) -> crate::protos::store::Conflict_Part { - let mut proto = crate::protos::store::Conflict_Part::new(); - proto.set_content(tree_value_to_proto(&part.value)); +fn conflict_part_to_proto(part: &ConflictPart) -> crate::protos::store::conflict::Part { + let mut proto = crate::protos::store::conflict::Part::new(); + proto.content = MessageField::some(tree_value_to_proto(&part.value)); proto } diff --git a/lib/src/simple_op_store.rs b/lib/src/simple_op_store.rs index 67a21659e..d74561d12 100644 --- a/lib/src/simple_op_store.rs +++ b/lib/src/simple_op_store.rs @@ -21,7 +21,7 @@ use std::path::PathBuf; use blake2::{Blake2b512, Digest}; use itertools::Itertools; -use protobuf::{Message, ProtobufError}; +use protobuf::{Message, MessageField}; use tempfile::{NamedTempFile, PersistError}; use crate::backend::{CommitId, MillisSinceEpoch, Timestamp}; @@ -43,8 +43,8 @@ impl From for OpStoreError { } } -impl From for OpStoreError { - fn from(err: ProtobufError) -> Self { +impl From for OpStoreError { + fn from(err: protobuf::Error) -> Self { OpStoreError::Other(err.to_string()) } } @@ -132,8 +132,8 @@ impl OpStore for SimpleOpStore { fn timestamp_to_proto(timestamp: &Timestamp) -> crate::protos::op_store::Timestamp { let mut proto = crate::protos::op_store::Timestamp::new(); - proto.set_millis_since_epoch(timestamp.timestamp.0); - proto.set_tz_offset(timestamp.tz_offset); + proto.millis_since_epoch = timestamp.timestamp.0; + proto.tz_offset = timestamp.tz_offset; proto } @@ -148,24 +148,24 @@ fn operation_metadata_to_proto( metadata: &OperationMetadata, ) -> crate::protos::op_store::OperationMetadata { let mut proto = crate::protos::op_store::OperationMetadata::new(); - proto.set_start_time(timestamp_to_proto(&metadata.start_time)); - proto.set_end_time(timestamp_to_proto(&metadata.end_time)); - proto.set_description(metadata.description.clone()); - proto.set_hostname(metadata.hostname.clone()); - proto.set_username(metadata.username.clone()); - proto.set_tags(metadata.tags.clone()); + proto.start_time = MessageField::some(timestamp_to_proto(&metadata.start_time)); + proto.end_time = MessageField::some(timestamp_to_proto(&metadata.end_time)); + proto.description = metadata.description.clone(); + proto.hostname = metadata.hostname.clone(); + proto.username = metadata.username.clone(); + proto.tags = metadata.tags.clone(); proto } fn operation_metadata_from_proto( proto: &crate::protos::op_store::OperationMetadata, ) -> OperationMetadata { - let start_time = timestamp_from_proto(proto.get_start_time()); - let end_time = timestamp_from_proto(proto.get_end_time()); - let description = proto.get_description().to_owned(); - let hostname = proto.get_hostname().to_owned(); - let username = proto.get_username().to_owned(); - let tags = proto.get_tags().clone(); + let start_time = timestamp_from_proto(&proto.start_time); + let end_time = timestamp_from_proto(&proto.end_time); + let description = proto.description.to_owned(); + let hostname = proto.hostname.to_owned(); + let username = proto.username.to_owned(); + let tags = proto.tags.clone(); OperationMetadata { start_time, end_time, @@ -178,11 +178,11 @@ fn operation_metadata_from_proto( fn operation_to_proto(operation: &Operation) -> crate::protos::op_store::Operation { let mut proto = crate::protos::op_store::Operation::new(); - proto.set_view_id(operation.view_id.as_bytes().to_vec()); + proto.view_id = operation.view_id.as_bytes().to_vec(); for parent in &operation.parents { proto.parents.push(parent.to_bytes()); } - proto.set_metadata(operation_metadata_to_proto(&operation.metadata)); + proto.metadata = MessageField::some(operation_metadata_to_proto(&operation.metadata)); proto } @@ -190,7 +190,7 @@ fn operation_from_proto(proto: &crate::protos::op_store::Operation) -> Operation let operation_id_from_proto = |parent: &Vec| OperationId::new(parent.clone()); let parents = proto.parents.iter().map(operation_id_from_proto).collect(); let view_id = ViewId::new(proto.view_id.clone()); - let metadata = operation_metadata_from_proto(proto.get_metadata()); + let metadata = operation_metadata_from_proto(&proto.metadata); Operation { view_id, parents, @@ -214,14 +214,14 @@ fn view_to_proto(view: &View) -> crate::protos::op_store::View { for (name, target) in &view.branches { let mut branch_proto = crate::protos::op_store::Branch::new(); - branch_proto.set_name(name.clone()); + branch_proto.name = name.clone(); if let Some(local_target) = &target.local_target { - branch_proto.set_local_target(ref_target_to_proto(local_target)); + branch_proto.local_target = MessageField::some(ref_target_to_proto(local_target)); } for (remote_name, target) in &target.remote_targets { let mut remote_branch_proto = crate::protos::op_store::RemoteBranch::new(); - remote_branch_proto.set_remote_name(remote_name.clone()); - remote_branch_proto.set_target(ref_target_to_proto(target)); + remote_branch_proto.remote_name = remote_name.clone(); + remote_branch_proto.target = MessageField::some(ref_target_to_proto(target)); branch_proto.remote_branches.push(remote_branch_proto); } proto.branches.push(branch_proto); @@ -229,20 +229,20 @@ fn view_to_proto(view: &View) -> crate::protos::op_store::View { for (name, target) in &view.tags { let mut tag_proto = crate::protos::op_store::Tag::new(); - tag_proto.set_name(name.clone()); - tag_proto.set_target(ref_target_to_proto(target)); + tag_proto.name = name.clone(); + tag_proto.target = MessageField::some(ref_target_to_proto(target)); proto.tags.push(tag_proto); } for (git_ref_name, target) in &view.git_refs { let mut git_ref_proto = crate::protos::op_store::GitRef::new(); - git_ref_proto.set_name(git_ref_name.clone()); - git_ref_proto.set_target(ref_target_to_proto(target)); + git_ref_proto.name = git_ref_name.clone(); + git_ref_proto.target = MessageField::some(ref_target_to_proto(target)); proto.git_refs.push(git_ref_proto); } if let Some(git_head) = &view.git_head { - proto.set_git_head(git_head.to_bytes()); + proto.git_head = git_head.to_bytes(); } proto @@ -282,7 +282,7 @@ fn view_from_proto(proto: &crate::protos::op_store::View) -> View { for remote_branch in &branch_proto.remote_branches { remote_targets.insert( remote_branch.remote_name.clone(), - ref_target_from_proto(remote_branch.target.get_ref()), + ref_target_from_proto(&remote_branch.target), ); } @@ -298,16 +298,14 @@ fn view_from_proto(proto: &crate::protos::op_store::View) -> View { for tag_proto in &proto.tags { view.tags.insert( tag_proto.name.clone(), - ref_target_from_proto(tag_proto.target.get_ref()), + ref_target_from_proto(&tag_proto.target), ); } for git_ref in &proto.git_refs { - if git_ref.has_target() { - view.git_refs.insert( - git_ref.name.clone(), - ref_target_from_proto(git_ref.target.as_ref().unwrap()), - ); + if let Some(target) = git_ref.target.as_ref() { + view.git_refs + .insert(git_ref.name.clone(), ref_target_from_proto(target)); } else { // Legacy format view.git_refs.insert( @@ -346,10 +344,10 @@ fn ref_target_to_proto(value: &RefTarget) -> crate::protos::op_store::RefTarget fn ref_target_from_proto(proto: &crate::protos::op_store::RefTarget) -> RefTarget { match proto.value.as_ref().unwrap() { - crate::protos::op_store::RefTarget_oneof_value::commit_id(id) => { + crate::protos::op_store::ref_target::Value::CommitId(id) => { RefTarget::Normal(CommitId::from_bytes(id)) } - crate::protos::op_store::RefTarget_oneof_value::conflict(conflict) => { + crate::protos::op_store::ref_target::Value::Conflict(conflict) => { let removes = conflict .removes .iter() diff --git a/lib/src/working_copy.rs b/lib/src/working_copy.rs index 30c27c2bf..4230520e9 100644 --- a/lib/src/working_copy.rs +++ b/lib/src/working_copy.rs @@ -28,7 +28,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::UNIX_EPOCH; -use protobuf::Message; +use protobuf::{EnumOrUnknown, Message, MessageField}; use tempfile::NamedTempFile; use thiserror::Error; @@ -91,7 +91,7 @@ pub struct TreeState { } fn file_state_from_proto(proto: &crate::protos::working_copy::FileState) -> FileState { - let file_type = match proto.file_type { + let file_type = match proto.file_type.enum_value_or_default() { crate::protos::working_copy::FileType::Normal => FileType::Normal { executable: false }, crate::protos::working_copy::FileType::Executable => FileType::Normal { executable: true }, crate::protos::working_copy::FileType::Symlink => FileType::Symlink, @@ -118,7 +118,7 @@ fn file_state_to_proto(file_state: &FileState) -> crate::protos::working_copy::F crate::protos::working_copy::FileType::Conflict } }; - proto.file_type = file_type; + proto.file_type = EnumOrUnknown::new(file_type); proto.mtime_millis_since_epoch = file_state.mtime.0; proto.size = file_state.size; proto @@ -137,8 +137,8 @@ fn file_states_from_proto( fn sparse_patterns_from_proto(proto: &crate::protos::working_copy::TreeState) -> Vec { let mut sparse_patterns = vec![]; - if proto.has_sparse_patterns() { - for prefix in &proto.get_sparse_patterns().prefixes { + if let Some(proto_sparse_patterns) = proto.sparse_patterns.as_ref() { + for prefix in &proto_sparse_patterns.prefixes { sparse_patterns.push(RepoPath::from_internal_string(prefix.as_str())); } } else { @@ -312,7 +312,7 @@ impl TreeState { .prefixes .push(path.to_internal_file_string()); } - proto.set_sparse_patterns(sparse_patterns); + proto.sparse_patterns = MessageField::some(sparse_patterns); let mut temp_file = NamedTempFile::new_in(&self.state_path).unwrap(); proto.write_to_writer(temp_file.as_file_mut()).unwrap();