mirror of
https://github.com/starship/starship.git
synced 2024-11-23 00:33:16 +01:00
feat: Adds Git State module for showing "REBASING 2/3", etc. (#276)
- Adds the git_state module. - Adds git_state to the default prompt order - Updates the documentation to describe the git_state module
This commit is contained in:
parent
4f17bae315
commit
eb724279da
@ -72,6 +72,7 @@ default_prompt_order = [
|
|||||||
"hostname",
|
"hostname",
|
||||||
"directory",
|
"directory",
|
||||||
"git_branch",
|
"git_branch",
|
||||||
|
"git_state",
|
||||||
"git_status",
|
"git_status",
|
||||||
"package",
|
"package",
|
||||||
"nodejs",
|
"nodejs",
|
||||||
@ -79,6 +80,7 @@ default_prompt_order = [
|
|||||||
"rust",
|
"rust",
|
||||||
"python",
|
"python",
|
||||||
"golang",
|
"golang",
|
||||||
|
"nix_shell",
|
||||||
"cmd_duration",
|
"cmd_duration",
|
||||||
"line_break",
|
"line_break",
|
||||||
"jobs",
|
"jobs",
|
||||||
@ -230,6 +232,37 @@ truncation_length = "4"
|
|||||||
truncation_symbol = ""
|
truncation_symbol = ""
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Git State
|
||||||
|
|
||||||
|
The `git_state` module will show in directories which are part of a git
|
||||||
|
repository, and where there is an operation in progress, such as: _REBASING_,
|
||||||
|
_BISECTING_, etc. If there is progress information (e.g., REBASING 3/10),
|
||||||
|
that information will be shown too.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
| ------------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `rebase` | `"REBASING"` | The text displayed when a `rebase` is in progress. |
|
||||||
|
| `merge` | `"MERGING"` | The text displayed when a `merge` is in progress. |
|
||||||
|
| `revert` | `"REVERTING"` | The text displayed when a `revert` is in progress. |
|
||||||
|
| `cherry_pick` | `"CHERRY-PICKING"` | The text displayed when a `cherry-pick` is in progress. |
|
||||||
|
| `bisect` | `"BISECTING"` | The text displayed when a `bisect` is in progress. |
|
||||||
|
| `am` | `"AM"` | The text displayed when an `apply-mailbox` (`git am`) is in progress. |
|
||||||
|
| `am_or_rebase` | `"AM/REBASE"` | The text displayed when an ambiguous `apply-mailbox` or `rebase` is in progress. |
|
||||||
|
| `progress_divider` | `"/"` | The symbol or text which will separate the current and total progress amounts. (e.g., `" of "`, for `"3 of 10"`) |
|
||||||
|
| `disabled` | `false` | Disables the `git_state` module. |
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# ~/.config/starship.toml
|
||||||
|
|
||||||
|
[git_state]
|
||||||
|
progress_divider = " of "
|
||||||
|
cherry_pick = "🍒 PICKING"
|
||||||
|
```
|
||||||
|
|
||||||
## Git Status
|
## Git Status
|
||||||
|
|
||||||
The `git_status` module shows symbols representing the state of the repo in your
|
The `git_status` module shows symbols representing the state of the repo in your
|
||||||
@ -277,7 +310,7 @@ The `hostname` module shows the system hostname.
|
|||||||
### Options
|
### Options
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
| ------------ | ------- | ------------------------------------------------------- |
|
| ---------- | ------- | ---------------------------------------------------- |
|
||||||
| `ssh_only` | `true` | Only show hostname when connected to an SSH session. |
|
| `ssh_only` | `true` | Only show hostname when connected to an SSH session. |
|
||||||
| `prefix` | `""` | Prefix to display immediately before the hostname. |
|
| `prefix` | `""` | Prefix to display immediately before the hostname. |
|
||||||
| `suffix` | `""` | Suffix to display immediately after the hostname. |
|
| `suffix` | `""` | Suffix to display immediately after the hostname. |
|
||||||
@ -379,7 +412,7 @@ The module will be shown if any of the following conditions are met:
|
|||||||
### Options
|
### Options
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
| ---------- | ------- | --------------------------- |
|
| ---------- | ------- | ------------------------------------------------------ |
|
||||||
| `symbol` | `"💎 "` | The symbol used before displaying the version of Ruby. |
|
| `symbol` | `"💎 "` | The symbol used before displaying the version of Ruby. |
|
||||||
| `disabled` | `false` | Disables the `ruby` module. |
|
| `disabled` | `false` | Disables the `ruby` module. |
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ pub const ALL_MODULES: &[&str] = &[
|
|||||||
"cmd_duration",
|
"cmd_duration",
|
||||||
"directory",
|
"directory",
|
||||||
"git_branch",
|
"git_branch",
|
||||||
|
"git_state",
|
||||||
"git_status",
|
"git_status",
|
||||||
"golang",
|
"golang",
|
||||||
"hostname",
|
"hostname",
|
||||||
|
166
src/modules/git_state.rs
Normal file
166
src/modules/git_state.rs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
use ansi_term::Color;
|
||||||
|
use git2::{Repository, RepositoryState};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use super::{Context, Module};
|
||||||
|
|
||||||
|
/// Creates a module with the state of the git repository at the current directory
|
||||||
|
///
|
||||||
|
/// During a git operation it will show: REBASING, BISECTING, MERGING, etc.
|
||||||
|
/// If the progress information is available (e.g. rebasing 3/10), it will show that too.
|
||||||
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
|
let mut module = context.new_module("git_state")?;
|
||||||
|
|
||||||
|
let repo_root = context.repo_root.as_ref()?;
|
||||||
|
let mut repository = Repository::open(repo_root).ok()?;
|
||||||
|
let state_description = get_state_description(&mut repository);
|
||||||
|
|
||||||
|
if let StateDescription::Clean = state_description {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.get_prefix().set_value("(");
|
||||||
|
module.get_suffix().set_value(") ");
|
||||||
|
module.set_style(Color::Yellow.bold());
|
||||||
|
|
||||||
|
let label = match state_description {
|
||||||
|
StateDescription::Label(label) => label,
|
||||||
|
StateDescription::LabelAndProgress(label, _) => label,
|
||||||
|
// Should only be possible if you've added a new variant to StateDescription
|
||||||
|
_ => panic!("Expected to have a label at this point in the control flow."),
|
||||||
|
};
|
||||||
|
|
||||||
|
module.new_segment(label.segment_name, label.message_default);
|
||||||
|
|
||||||
|
if let StateDescription::LabelAndProgress(_, progress) = state_description {
|
||||||
|
module.new_segment("progress_current", &format!(" {}", progress.current));
|
||||||
|
module.new_segment("progress_divider", "/");
|
||||||
|
module.new_segment("progress_total", &format!("{}", progress.total));
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(module)
|
||||||
|
}
|
||||||
|
|
||||||
|
static MERGE_LABEL: StateLabel = StateLabel {
|
||||||
|
segment_name: "merge",
|
||||||
|
message_default: "MERGING",
|
||||||
|
};
|
||||||
|
|
||||||
|
static REVERT_LABEL: StateLabel = StateLabel {
|
||||||
|
segment_name: "revert",
|
||||||
|
message_default: "REVERTING",
|
||||||
|
};
|
||||||
|
|
||||||
|
static CHERRY_LABEL: StateLabel = StateLabel {
|
||||||
|
segment_name: "cherry_pick",
|
||||||
|
message_default: "CHERRY-PICKING",
|
||||||
|
};
|
||||||
|
|
||||||
|
static BISECT_LABEL: StateLabel = StateLabel {
|
||||||
|
segment_name: "bisect",
|
||||||
|
message_default: "BISECTING",
|
||||||
|
};
|
||||||
|
|
||||||
|
static AM_LABEL: StateLabel = StateLabel {
|
||||||
|
segment_name: "am",
|
||||||
|
message_default: "AM",
|
||||||
|
};
|
||||||
|
|
||||||
|
static REBASE_LABEL: StateLabel = StateLabel {
|
||||||
|
segment_name: "rebase",
|
||||||
|
message_default: "REBASING",
|
||||||
|
};
|
||||||
|
|
||||||
|
static AM_OR_REBASE_LABEL: StateLabel = StateLabel {
|
||||||
|
segment_name: "am_or_rebase",
|
||||||
|
message_default: "AM/REBASE",
|
||||||
|
};
|
||||||
|
|
||||||
|
fn get_state_description(repository: &mut Repository) -> StateDescription {
|
||||||
|
match repository.state() {
|
||||||
|
RepositoryState::Clean => StateDescription::Clean,
|
||||||
|
RepositoryState::Merge => StateDescription::Label(&MERGE_LABEL),
|
||||||
|
RepositoryState::Revert => StateDescription::Label(&REVERT_LABEL),
|
||||||
|
RepositoryState::RevertSequence => StateDescription::Label(&REVERT_LABEL),
|
||||||
|
RepositoryState::CherryPick => StateDescription::Label(&CHERRY_LABEL),
|
||||||
|
RepositoryState::CherryPickSequence => StateDescription::Label(&CHERRY_LABEL),
|
||||||
|
RepositoryState::Bisect => StateDescription::Label(&BISECT_LABEL),
|
||||||
|
RepositoryState::ApplyMailbox => StateDescription::Label(&AM_LABEL),
|
||||||
|
RepositoryState::ApplyMailboxOrRebase => StateDescription::Label(&AM_OR_REBASE_LABEL),
|
||||||
|
RepositoryState::Rebase => describe_rebase(repository),
|
||||||
|
RepositoryState::RebaseInteractive => describe_rebase(repository),
|
||||||
|
RepositoryState::RebaseMerge => describe_rebase(repository),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn describe_rebase(repository: &mut Repository) -> StateDescription {
|
||||||
|
/*
|
||||||
|
* Sadly, libgit2 seems to have some issues with reading the state of
|
||||||
|
* interactive rebases. So, instead, we'll poke a few of the .git files
|
||||||
|
* ourselves. This might be worth re-visiting this in the future...
|
||||||
|
*
|
||||||
|
* The following is based heavily on: https://github.com/magicmonty/bash-git-prompt
|
||||||
|
*/
|
||||||
|
|
||||||
|
let just_label = StateDescription::Label(&REBASE_LABEL);
|
||||||
|
|
||||||
|
let dot_git = repository
|
||||||
|
.workdir()
|
||||||
|
.and_then(|d| Some(d.join(Path::new(".git"))));
|
||||||
|
|
||||||
|
let dot_git = match dot_git {
|
||||||
|
None => {
|
||||||
|
// We didn't find the .git directory.
|
||||||
|
// Something very odd is going on. We'll just back away slowly.
|
||||||
|
return just_label;
|
||||||
|
}
|
||||||
|
Some(path) => path,
|
||||||
|
};
|
||||||
|
|
||||||
|
let has_path = |relative_path: &str| {
|
||||||
|
let path = dot_git.join(Path::new(relative_path));
|
||||||
|
path.exists()
|
||||||
|
};
|
||||||
|
|
||||||
|
let file_to_usize = |relative_path: &str| {
|
||||||
|
let path = dot_git.join(Path::new(relative_path));
|
||||||
|
let contents = crate::utils::read_file(path).ok()?;
|
||||||
|
let quantity = contents.trim().parse::<usize>().ok()?;
|
||||||
|
Some(quantity)
|
||||||
|
};
|
||||||
|
|
||||||
|
let paths_to_progress = |current_path: &str, total_path: &str| {
|
||||||
|
let current = file_to_usize(current_path)?;
|
||||||
|
let total = file_to_usize(total_path)?;
|
||||||
|
Some(StateProgress { current, total })
|
||||||
|
};
|
||||||
|
|
||||||
|
let progress = if has_path("rebase-merge") {
|
||||||
|
paths_to_progress("rebase-merge/msgnum", "rebase-merge/end")
|
||||||
|
} else if has_path("rebase-apply") {
|
||||||
|
paths_to_progress("rebase-apply/next", "rebase-apply/last")
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
match progress {
|
||||||
|
None => just_label,
|
||||||
|
Some(progress) => StateDescription::LabelAndProgress(&REBASE_LABEL, progress),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum StateDescription {
|
||||||
|
Clean,
|
||||||
|
Label(&'static StateLabel),
|
||||||
|
LabelAndProgress(&'static StateLabel, StateProgress),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StateLabel {
|
||||||
|
segment_name: &'static str,
|
||||||
|
message_default: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StateProgress {
|
||||||
|
current: usize,
|
||||||
|
total: usize,
|
||||||
|
}
|
@ -3,6 +3,7 @@ mod character;
|
|||||||
mod cmd_duration;
|
mod cmd_duration;
|
||||||
mod directory;
|
mod directory;
|
||||||
mod git_branch;
|
mod git_branch;
|
||||||
|
mod git_state;
|
||||||
mod git_status;
|
mod git_status;
|
||||||
mod golang;
|
mod golang;
|
||||||
mod hostname;
|
mod hostname;
|
||||||
@ -34,6 +35,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
|||||||
"line_break" => line_break::module(context),
|
"line_break" => line_break::module(context),
|
||||||
"package" => package::module(context),
|
"package" => package::module(context),
|
||||||
"git_branch" => git_branch::module(context),
|
"git_branch" => git_branch::module(context),
|
||||||
|
"git_state" => git_state::module(context),
|
||||||
"git_status" => git_status::module(context),
|
"git_status" => git_status::module(context),
|
||||||
"username" => username::module(context),
|
"username" => username::module(context),
|
||||||
#[cfg(feature = "battery")]
|
#[cfg(feature = "battery")]
|
||||||
|
@ -16,6 +16,7 @@ const DEFAULT_PROMPT_ORDER: &[&str] = &[
|
|||||||
"hostname",
|
"hostname",
|
||||||
"directory",
|
"directory",
|
||||||
"git_branch",
|
"git_branch",
|
||||||
|
"git_state",
|
||||||
"git_status",
|
"git_status",
|
||||||
"package",
|
"package",
|
||||||
"nodejs",
|
"nodejs",
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Result};
|
use std::io::{Read, Result};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
/// Return the string contents of a file
|
/// Return the string contents of a file
|
||||||
pub fn read_file(file_name: &str) -> Result<String> {
|
pub fn read_file<P: AsRef<Path>>(file_name: P) -> Result<String> {
|
||||||
let mut file = File::open(file_name)?;
|
let mut file = File::open(file_name)?;
|
||||||
let mut data = String::new();
|
let mut data = String::new();
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use lazy_static::lazy_static;
|
|||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::{env, io, process};
|
use std::{env, fs, io, process};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref MANIFEST_DIR: &'static Path = Path::new(env!("CARGO_MANIFEST_DIR"));
|
static ref MANIFEST_DIR: &'static Path = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||||
@ -25,7 +25,8 @@ pub fn render_prompt() -> process::Command {
|
|||||||
|
|
||||||
/// Render a specific starship module by name
|
/// Render a specific starship module by name
|
||||||
pub fn render_module(module_name: &str) -> process::Command {
|
pub fn render_module(module_name: &str) -> process::Command {
|
||||||
let mut command = process::Command::new("./target/debug/starship");
|
let binary = fs::canonicalize("./target/debug/starship").unwrap();
|
||||||
|
let mut command = process::Command::new(binary);
|
||||||
|
|
||||||
command
|
command
|
||||||
.arg("module")
|
.arg("module")
|
||||||
|
177
tests/testsuite/git_state.rs
Normal file
177
tests/testsuite/git_state.rs
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
use super::common;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::io::{self, Error, ErrorKind, Write};
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn shows_rebasing() -> io::Result<()> {
|
||||||
|
let repo_dir = create_repo_with_conflict()?;
|
||||||
|
let path = path_str(&repo_dir)?;
|
||||||
|
|
||||||
|
run_git_cmd(&["rebase", "other-branch"], Some(path), false)?;
|
||||||
|
|
||||||
|
let output = common::render_module("git_state")
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
let text = String::from_utf8(output.stdout).unwrap();
|
||||||
|
assert!(text.contains("REBASING 1/1"));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn shows_merging() -> io::Result<()> {
|
||||||
|
let repo_dir = create_repo_with_conflict()?;
|
||||||
|
let path = path_str(&repo_dir)?;
|
||||||
|
|
||||||
|
run_git_cmd(&["merge", "other-branch"], Some(path), false)?;
|
||||||
|
|
||||||
|
let output = common::render_module("git_state")
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
let text = String::from_utf8(output.stdout).unwrap();
|
||||||
|
assert!(text.contains("MERGING"));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn shows_cherry_picking() -> io::Result<()> {
|
||||||
|
let repo_dir = create_repo_with_conflict()?;
|
||||||
|
let path = path_str(&repo_dir)?;
|
||||||
|
|
||||||
|
run_git_cmd(&["cherry-pick", "other-branch"], Some(path), false)?;
|
||||||
|
|
||||||
|
let output = common::render_module("git_state")
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
let text = String::from_utf8(output.stdout).unwrap();
|
||||||
|
assert!(text.contains("CHERRY-PICKING"));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn shows_bisecting() -> io::Result<()> {
|
||||||
|
let repo_dir = create_repo_with_conflict()?;
|
||||||
|
let path = path_str(&repo_dir)?;
|
||||||
|
|
||||||
|
run_git_cmd(&["bisect", "start"], Some(path), false)?;
|
||||||
|
|
||||||
|
let output = common::render_module("git_state")
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
let text = String::from_utf8(output.stdout).unwrap();
|
||||||
|
assert!(text.contains("BISECTING"));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn shows_reverting() -> io::Result<()> {
|
||||||
|
let repo_dir = create_repo_with_conflict()?;
|
||||||
|
let path = path_str(&repo_dir)?;
|
||||||
|
|
||||||
|
run_git_cmd(&["revert", "--no-commit", "HEAD~1"], Some(path), false)?;
|
||||||
|
|
||||||
|
let output = common::render_module("git_state")
|
||||||
|
.current_dir(path)
|
||||||
|
.output()?;
|
||||||
|
let text = String::from_utf8(output.stdout).unwrap();
|
||||||
|
assert!(text.contains("REVERTING"));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_git_cmd<A, S>(args: A, dir: Option<&str>, expect_ok: bool) -> io::Result<()>
|
||||||
|
where
|
||||||
|
A: IntoIterator<Item = S>,
|
||||||
|
S: AsRef<OsStr>,
|
||||||
|
{
|
||||||
|
let mut command = Command::new("git");
|
||||||
|
command
|
||||||
|
.args(args)
|
||||||
|
.stdout(Stdio::null())
|
||||||
|
.stderr(Stdio::null())
|
||||||
|
.stdin(Stdio::null());
|
||||||
|
|
||||||
|
if let Some(dir) = dir {
|
||||||
|
command.current_dir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = command.status()?;
|
||||||
|
|
||||||
|
if expect_ok && !status.success() {
|
||||||
|
Err(Error::from(ErrorKind::Other))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_repo_with_conflict() -> io::Result<tempfile::TempDir> {
|
||||||
|
let repo_dir = common::new_tempdir()?;
|
||||||
|
let path = path_str(&repo_dir)?;
|
||||||
|
let conflicted_file = repo_dir.path().join("the_file");
|
||||||
|
|
||||||
|
let write_file = |text: &str| {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&conflicted_file)?;
|
||||||
|
write!(file, "{}", text)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialise a new git repo
|
||||||
|
run_git_cmd(&["init", "--quiet", path], None, true)?;
|
||||||
|
|
||||||
|
// Set local author info
|
||||||
|
run_git_cmd(
|
||||||
|
&["config", "--local", "user.email", "starship@example.com"],
|
||||||
|
Some(path),
|
||||||
|
true,
|
||||||
|
)?;
|
||||||
|
run_git_cmd(
|
||||||
|
&["config", "--local", "user.name", "starship"],
|
||||||
|
Some(path),
|
||||||
|
true,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Write a file on master and commit it
|
||||||
|
write_file("Version A")?;
|
||||||
|
run_git_cmd(&["add", "the_file"], Some(path), true)?;
|
||||||
|
run_git_cmd(&["commit", "--message", "Commit A"], Some(path), true)?;
|
||||||
|
|
||||||
|
// Switch to another branch, and commit a change to the file
|
||||||
|
run_git_cmd(&["checkout", "-b", "other-branch"], Some(path), true)?;
|
||||||
|
write_file("Version B")?;
|
||||||
|
run_git_cmd(
|
||||||
|
&["commit", "--all", "--message", "Commit B"],
|
||||||
|
Some(path),
|
||||||
|
true,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Switch back to master, and commit a third change to the file
|
||||||
|
run_git_cmd(&["checkout", "master"], Some(path), true)?;
|
||||||
|
write_file("Version C")?;
|
||||||
|
run_git_cmd(
|
||||||
|
&["commit", "--all", "--message", "Commit C"],
|
||||||
|
Some(path),
|
||||||
|
true,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(repo_dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_str(repo_dir: &tempfile::TempDir) -> io::Result<&str> {
|
||||||
|
repo_dir
|
||||||
|
.path()
|
||||||
|
.to_str()
|
||||||
|
.ok_or_else(|| Error::from(ErrorKind::Other))
|
||||||
|
}
|
@ -4,6 +4,7 @@ mod common;
|
|||||||
mod configuration;
|
mod configuration;
|
||||||
mod directory;
|
mod directory;
|
||||||
mod git_branch;
|
mod git_branch;
|
||||||
|
mod git_state;
|
||||||
mod git_status;
|
mod git_status;
|
||||||
mod golang;
|
mod golang;
|
||||||
mod hostname;
|
mod hostname;
|
||||||
|
Loading…
Reference in New Issue
Block a user