forked from mirrors/jj
git: add a hidden submodule subcommand
Add the `submodule` subcommand, which will remain hidden while we are polishing up the submodules feature. Also, add a debugging-only sub-subcommand `print-gitmodules` that tests our .gitmodules parser with the .gitmodules in the working copy.
This commit is contained in:
parent
7afaa2487b
commit
777b786c53
3 changed files with 128 additions and 3 deletions
|
@ -31,7 +31,7 @@ use indexmap::IndexSet;
|
|||
use itertools::Itertools;
|
||||
use jujutsu_lib::backend::{BackendError, ChangeId, CommitId, ObjectId, TreeId};
|
||||
use jujutsu_lib::commit::Commit;
|
||||
use jujutsu_lib::git::{GitExportError, GitImportError};
|
||||
use jujutsu_lib::git::{GitConfigParseError, GitExportError, GitImportError};
|
||||
use jujutsu_lib::git_backend::GitBackend;
|
||||
use jujutsu_lib::gitignore::GitIgnoreFile;
|
||||
use jujutsu_lib::hex_util::to_reverse_hex;
|
||||
|
@ -325,6 +325,12 @@ impl From<clap::Error> for CommandError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<GitConfigParseError> for CommandError {
|
||||
fn from(err: GitConfigParseError) -> Self {
|
||||
CommandError::InternalError(format!("Failed to parse Git config: {err} "))
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle to initialize or change tracing subscription.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TracingSubscription {
|
||||
|
|
|
@ -8,12 +8,13 @@ use std::time::Instant;
|
|||
|
||||
use clap::{ArgGroup, Subcommand};
|
||||
use itertools::Itertools;
|
||||
use jujutsu_lib::backend::ObjectId;
|
||||
use jujutsu_lib::git::{self, GitFetchError, GitPushError, GitRefUpdate};
|
||||
use jujutsu_lib::backend::{ObjectId, TreeValue};
|
||||
use jujutsu_lib::git::{self, parse_gitmodules, GitFetchError, GitPushError, GitRefUpdate};
|
||||
use jujutsu_lib::git_backend::GitBackend;
|
||||
use jujutsu_lib::op_store::{BranchTarget, RefTarget};
|
||||
use jujutsu_lib::refs::{classify_branch_push_action, BranchPushAction, BranchPushUpdate};
|
||||
use jujutsu_lib::repo::Repo;
|
||||
use jujutsu_lib::repo_path::RepoPath;
|
||||
use jujutsu_lib::revset::{self, RevsetIteratorExt as _};
|
||||
use jujutsu_lib::settings::{ConfigResultExt as _, UserSettings};
|
||||
use jujutsu_lib::store::Store;
|
||||
|
@ -43,6 +44,8 @@ pub enum GitCommands {
|
|||
Push(GitPushArgs),
|
||||
Import(GitImportArgs),
|
||||
Export(GitExportArgs),
|
||||
#[command(subcommand, hide = true)]
|
||||
Submodule(GitSubmoduleCommands),
|
||||
}
|
||||
|
||||
/// Manage Git remotes
|
||||
|
@ -155,6 +158,23 @@ pub struct GitImportArgs {}
|
|||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct GitExportArgs {}
|
||||
|
||||
/// FOR INTERNAL USE ONLY Interact with git submodules
|
||||
#[derive(Subcommand, Clone, Debug)]
|
||||
pub enum GitSubmoduleCommands {
|
||||
/// Print the relevant contents from .gitmodules. For debugging purposes
|
||||
/// only.
|
||||
PrintGitmodules(GitSubmodulePrintGitmodulesArgs),
|
||||
}
|
||||
|
||||
/// Print debugging info about Git submodules
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
#[command(hide = true)]
|
||||
pub struct GitSubmodulePrintGitmodulesArgs {
|
||||
/// Read .gitmodules from the given revision.
|
||||
#[arg(long, short = 'r', default_value = "@")]
|
||||
revisions: RevisionArg,
|
||||
}
|
||||
|
||||
fn get_git_repo(store: &Store) -> Result<git2::Repository, CommandError> {
|
||||
match store.backend_impl().downcast_ref::<GitBackend>() {
|
||||
None => Err(user_error("The repo is not backed by a git repo")),
|
||||
|
@ -1016,6 +1036,37 @@ fn cmd_git_export(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn cmd_git_submodule_print_gitmodules(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
args: &GitSubmodulePrintGitmodulesArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let workspace_command = command.workspace_helper(ui)?;
|
||||
let repo = workspace_command.repo();
|
||||
let commit = workspace_command.resolve_single_rev(&args.revisions)?;
|
||||
let gitmodules_path = RepoPath::from_internal_string(".gitmodules");
|
||||
let mut gitmodules_file = match commit.tree().path_value(&gitmodules_path) {
|
||||
None => {
|
||||
writeln!(ui, "No submodules!")?;
|
||||
return Ok(());
|
||||
}
|
||||
Some(TreeValue::File { id, .. }) => repo.store().read_file(&gitmodules_path, &id)?,
|
||||
_ => {
|
||||
return Err(user_error(".gitmodules is not a file."));
|
||||
}
|
||||
};
|
||||
|
||||
let submodules = parse_gitmodules(&mut gitmodules_file)?;
|
||||
for (name, submodule) in submodules {
|
||||
writeln!(
|
||||
ui,
|
||||
"name:{}\nurl:{}\npath:{}\n\n",
|
||||
name, submodule.url, submodule.path
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn cmd_git(
|
||||
ui: &mut Ui,
|
||||
command: &CommandHelper,
|
||||
|
@ -1039,5 +1090,8 @@ pub fn cmd_git(
|
|||
GitCommands::Push(command_matches) => cmd_git_push(ui, command, command_matches),
|
||||
GitCommands::Import(command_matches) => cmd_git_import(ui, command, command_matches),
|
||||
GitCommands::Export(command_matches) => cmd_git_export(ui, command, command_matches),
|
||||
GitCommands::Submodule(GitSubmoduleCommands::PrintGitmodules(command_matches)) => {
|
||||
cmd_git_submodule_print_gitmodules(ui, command, command_matches)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
65
tests/test_git_submodule.rs
Normal file
65
tests/test_git_submodule.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Copyright 2020 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::common::TestEnvironment;
|
||||
|
||||
pub mod common;
|
||||
|
||||
#[test]
|
||||
fn test_gitsubmodule_print_gitmodules() {
|
||||
let test_env = TestEnvironment::default();
|
||||
let workspace_root = test_env.env_root().join("repo");
|
||||
git2::Repository::init(&workspace_root).unwrap();
|
||||
test_env.jj_cmd_success(&workspace_root, &["init", "--git-repo", "."]);
|
||||
|
||||
std::fs::write(
|
||||
workspace_root.join(".gitmodules"),
|
||||
"
|
||||
[submodule \"old\"]
|
||||
path = old
|
||||
url = https://github.com/old/old.git
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
test_env.jj_cmd_success(&workspace_root, &["new"]);
|
||||
|
||||
std::fs::write(
|
||||
workspace_root.join(".gitmodules"),
|
||||
"
|
||||
[submodule \"new\"]
|
||||
path = new
|
||||
url = https://github.com/new/new.git
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&workspace_root,
|
||||
&["git", "submodule", "print-gitmodules", "-r", "@-"],
|
||||
);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
name:old
|
||||
url:https://github.com/old/old.git
|
||||
path:old
|
||||
"###);
|
||||
|
||||
let stdout =
|
||||
test_env.jj_cmd_success(&workspace_root, &["git", "submodule", "print-gitmodules"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
name:new
|
||||
url:https://github.com/new/new.git
|
||||
path:new
|
||||
"###);
|
||||
}
|
Loading…
Reference in a new issue