jj_cli/commands/git/
mod.rs1mod clone;
16mod colocation;
17mod export;
18mod fetch;
19mod import;
20mod init;
21mod push;
22mod remote;
23mod root;
24
25use std::io::Write as _;
26use std::path::Path;
27
28use clap::Subcommand;
29use clap::ValueEnum;
30use jj_lib::config::ConfigFile;
31use jj_lib::config::ConfigSource;
32use jj_lib::git;
33use jj_lib::git::UnexpectedGitBackendError;
34use jj_lib::ref_name::RemoteNameBuf;
35use jj_lib::ref_name::RemoteRefSymbol;
36use jj_lib::store::Store;
37
38use self::clone::GitCloneArgs;
39use self::clone::cmd_git_clone;
40use self::colocation::GitColocationCommand;
41use self::colocation::cmd_git_colocation;
42use self::export::GitExportArgs;
43use self::export::cmd_git_export;
44use self::fetch::GitFetchArgs;
45use self::fetch::cmd_git_fetch;
46use self::import::GitImportArgs;
47use self::import::cmd_git_import;
48use self::init::GitInitArgs;
49use self::init::cmd_git_init;
50use self::push::GitPushArgs;
51use self::push::cmd_git_push;
52pub use self::push::is_push_operation;
53use self::remote::RemoteCommand;
54use self::remote::cmd_git_remote;
55use self::root::GitRootArgs;
56use self::root::cmd_git_root;
57use crate::cli_util::CommandHelper;
58use crate::cli_util::WorkspaceCommandHelper;
59use crate::command_error::CommandError;
60use crate::command_error::user_error_with_message;
61use crate::ui::Ui;
62
63#[derive(Subcommand, Clone, Debug)]
73pub enum GitCommand {
74 Clone(GitCloneArgs),
75 #[command(subcommand)]
76 Colocation(GitColocationCommand),
77 Export(GitExportArgs),
78 Fetch(GitFetchArgs),
79 Import(GitImportArgs),
80 Init(GitInitArgs),
81 Push(GitPushArgs),
82 #[command(subcommand)]
83 Remote(RemoteCommand),
84 Root(GitRootArgs),
85}
86
87pub fn cmd_git(
88 ui: &mut Ui,
89 command: &CommandHelper,
90 subcommand: &GitCommand,
91) -> Result<(), CommandError> {
92 match subcommand {
93 GitCommand::Clone(args) => cmd_git_clone(ui, command, args),
94 GitCommand::Colocation(subcommand) => cmd_git_colocation(ui, command, subcommand),
95 GitCommand::Export(args) => cmd_git_export(ui, command, args),
96 GitCommand::Fetch(args) => cmd_git_fetch(ui, command, args),
97 GitCommand::Import(args) => cmd_git_import(ui, command, args),
98 GitCommand::Init(args) => cmd_git_init(ui, command, args),
99 GitCommand::Push(args) => cmd_git_push(ui, command, args),
100 GitCommand::Remote(args) => cmd_git_remote(ui, command, args),
101 GitCommand::Root(args) => cmd_git_root(ui, command, args),
102 }
103}
104
105pub fn maybe_add_gitignore(workspace_command: &WorkspaceCommandHelper) -> Result<(), CommandError> {
106 if workspace_command.working_copy_shared_with_git() {
107 std::fs::write(
108 workspace_command
109 .workspace_root()
110 .join(".jj")
111 .join(".gitignore"),
112 "/*\n",
113 )
114 .map_err(|e| user_error_with_message("Failed to write .jj/.gitignore file", e))
115 } else {
116 Ok(())
117 }
118}
119
120fn get_single_remote(store: &Store) -> Result<Option<RemoteNameBuf>, UnexpectedGitBackendError> {
121 let mut names = git::get_all_remote_names(store)?;
122 Ok(match names.len() {
123 1 => names.pop(),
124 _ => None,
125 })
126}
127
128fn write_repository_level_trunk_alias(
130 ui: &Ui,
131 repo_path: &Path,
132 symbol: RemoteRefSymbol<'_>,
133) -> Result<(), CommandError> {
134 let mut file = ConfigFile::load_or_empty(ConfigSource::Repo, repo_path.join("config.toml"))?;
135 file.set_value(["revset-aliases", "trunk()"], symbol.to_string())
136 .expect("initial repo config shouldn't have invalid values");
137 file.save()?;
138 writeln!(
139 ui.status(),
140 "Setting the revset alias `trunk()` to `{symbol}`",
141 )?;
142 Ok(())
143}
144
145#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
146enum FetchTagsMode {
147 All,
149
150 Included,
153
154 None,
156}
157
158impl FetchTagsMode {
159 fn as_fetch_tags(&self) -> gix::remote::fetch::Tags {
160 match self {
161 Self::All => gix::remote::fetch::Tags::All,
162 Self::Included => gix::remote::fetch::Tags::Included,
163 Self::None => gix::remote::fetch::Tags::None,
164 }
165 }
166}