use super::git_error::{failed, Failure};
use super::git_ops::step;
use super::git_resolve::conflicts;
use super::git_run::Git;
pub(super) enum Shared {
Local,
Waiting,
Pushed { sent: bool },
}
pub(super) fn has_upstream(git: &Git) -> bool {
git.text(&["rev-parse", "--abbrev-ref", "@{upstream}"])
.is_some()
}
pub(super) fn pull(git: &Git) -> Result<bool, Failure> {
let out = git.run(&["pull", "--rebase", "--autostash"])?;
if !conflicts(git).is_empty() {
return Ok(false);
}
if out.ok() {
Ok(true)
} else {
Err(failed(&out))
}
}
pub(super) fn first_remote(git: &Git) -> Option<String> {
let remotes = git.text(&["remote"])?;
let first = remotes.lines().next()?;
Some(
remotes
.lines()
.find(|r| *r == "origin")
.unwrap_or(first)
.into(),
)
}
pub(super) fn share(git: &Git) -> Result<Shared, Failure> {
let Some(remote) = first_remote(git) else {
return Ok(Shared::Local);
};
if has_upstream(git) {
if !pull(git)? {
return Ok(Shared::Waiting);
}
let sent = git
.text(&["rev-list", "--count", "@{upstream}..HEAD"])
.is_some_and(|n| n != "0");
step(git, &["push"])?;
return Ok(Shared::Pushed { sent });
}
let branch = git
.text(&["symbolic-ref", "--short", "HEAD"])
.unwrap_or_default();
step(git, &["push", "--set-upstream", &remote, &branch])?;
Ok(Shared::Pushed { sent: true })
}