Skip to content

Commit 15a089a

Browse files
committed
Initial but absorb implementation
1 parent 5e16f25 commit 15a089a

File tree

4 files changed

+62
-1
lines changed

4 files changed

+62
-1
lines changed

crates/but/src/absorb/mod.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use but_settings::AppSettings;
2+
use gitbutler_command_context::CommandContext;
3+
use gitbutler_project::Project;
4+
5+
use crate::{id::CliId, rub::parse_sources};
6+
7+
/// Amends changes into the appropriate commits where they belong.
8+
///
9+
/// The semantic for finding "the appropriate commit" is as follows
10+
/// - Changes are amended into the topmost commit of the leftmost (first) lane (branch)
11+
/// - If a change is assigned to a particular lane (branch), it will be amended into a commit there
12+
/// - If there are no commits in this branch, a new commit is created
13+
/// - If a change has a dependency to a particular commit, it will be amended into that particular commit
14+
///
15+
/// Optionally an identifier to an Uncommitted File or a Branch (stack) may be provided.
16+
///
17+
/// If an Uncommitted File id is provided, absorb will be peformed for just that file
18+
/// If a Branch (stack) id is provided, absorb will be performed for all changes assigned to that stack
19+
/// If no source is provided, absorb is performed for all uncommitted changes
20+
pub(crate) fn handle(project: &Project, _json: bool, source: Option<&str>) -> anyhow::Result<()> {
21+
let ctx = &mut CommandContext::open(project, AppSettings::load_from_default_path_creating()?)?;
22+
let source: Option<CliId> = source
23+
.and_then(|s| parse_sources(ctx, s).ok())
24+
.and_then(|s| {
25+
s.into_iter().find(|s| {
26+
matches!(s, CliId::UncommittedFile { .. }) || matches!(s, CliId::Branch { .. })
27+
})
28+
});
29+
if let Some(source) = source {
30+
match source {
31+
CliId::UncommittedFile {
32+
path: _,
33+
assignment: _,
34+
} => {
35+
// Absorb this particular file
36+
}
37+
CliId::Branch { name: _ } => {
38+
// Absorb everything that is assigned to this lane
39+
}
40+
_ => {
41+
// Invalid source - error out
42+
}
43+
}
44+
} else {
45+
// Try to absorb everhting uncommitted
46+
}
47+
Ok(())
48+
}

crates/but/src/args.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,12 @@ For examples see `but rub --help`."
186186
#[clap(value_enum)]
187187
shell: Option<clap_complete::Shell>,
188188
},
189+
Absorb {
190+
/// If the CliID is an uncommitted change - the change will be absorbed
191+
/// If the CliID is a stack - anything assigned to the stack will be absorbed accordingly
192+
/// If not provided, everything that is uncommitted will be absorbed
193+
source: Option<String>,
194+
},
189195
}
190196

191197
#[derive(Debug, Clone, Copy, clap::ValueEnum, Default)]

crates/but/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use colored::Colorize;
1010
use gix::date::time::CustomFormat;
1111
use metrics::{Event, Metrics, Props, metrics_if_configured};
1212

13+
mod absorb;
1314
mod base;
1415
mod branch;
1516
mod command;
@@ -327,6 +328,12 @@ async fn match_subcommand(
327328
metrics_if_configured(app_settings, CommandName::Snapshot, props(start, &result)).ok();
328329
result
329330
}
331+
Subcommands::Absorb { source } => {
332+
let project = get_or_init_project(&args.current_dir)?;
333+
let result = absorb::handle(&project, args.json, source.as_deref());
334+
metrics_if_configured(app_settings, CommandName::Snapshot, props(start, &result)).ok();
335+
result
336+
}
330337
Subcommands::Init { repo } => init::repo(&args.current_dir, args.json, *repo)
331338
.context("Failed to initialize GitButler project."),
332339
Subcommands::Forge(forge::integration::Platform { cmd }) => {

crates/but/src/rub/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ fn ids(
166166
Ok((sources, target_result[0].clone()))
167167
}
168168

169-
fn parse_sources(ctx: &mut CommandContext, source: &str) -> anyhow::Result<Vec<CliId>> {
169+
pub(crate) fn parse_sources(ctx: &mut CommandContext, source: &str) -> anyhow::Result<Vec<CliId>> {
170170
// Check if it's a range (contains '-')
171171
if source.contains('-') {
172172
parse_range(ctx, source)

0 commit comments

Comments
 (0)