sync command #12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "cmd-sync"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Added sync command
This is the core command for
sac. It is used to stage, commit and sync changes with the remote.Per default it will execute:
git add .git commit -m "MESSAGE"git pushIf the push command fails, it will try to pull changes first and afterwards push again.
A merge conflict should be handled gracefully. This means to inform the user to resolve the merge conflict inside a Editor.
After resolving the merge conflicts
sac syncshould be able to be run to finish the merge process and afterwards sync again.TODO
Improve error messages
811d0c063df411a6df6fTODO
implement a check before commiting code, that there are no unresolved merge conflicts (
git diff --check).There should be an option to ignore this check with a flag (
--ignore-no-merge--allow-unresolved) because one might want to showcase a merge conflict layout, which would (most likely) be detected as a merge conflict itselfIssue
when inside a subdirectory, the git repo will not be detected, which will lead to and error.
Test
This is the main feature of
sacso testing might take a bit longer...A remote repository is needed for testing as well as two clones of said repository.
Create commit
(The commit message should be:
sac synchronization)Create commit (with message)
The commit should have the given commit message.
Multiline messages should be supported
Create commit with no changes
This should error
Create local commit
This should create the commit only locally and not sync it with the remote
Sync only remote
This should pull the
remote.txtfile into clone 2, butnot-remote.txtshould be unstaged (and not on the remote)Sync remote (ahead)
This should pull
ahead.txtand pushchange.txtafterwards.commit order:
"comes first""comes second"Sync remote (merge conflict)
This should result in a merge conflict.
Commit (while merge conflict)
Resolve conflicts
This should resolve the merge conflicts and sync them with the remote
No internet
This should fail to sync to the remote with a usefull error message
WIP: sync commandto sync commandIst nicht alles so relevant. Wenn du noch fragen zu irgendwas hast, schreib mir nochmal. Ich schau hier nicht so auf die notifications
@ -0,0 +8,20 @@/// This is the same as running:/// - git add ./// - git commit -m "sac synchronization"/// - git push/// If the remote is ahead, the push is retried with the following commands:/// - git pull --rebase/// - git push#[clap(verbatim_doc_comment)]pub struct Cmd {#[arg(short,long,value_name = "message",default_value = "sac synchronization")]/// custom message for the changesmessage: String,#[arg(short, long, default_value = "false")]/// commit changes only to the local rempoTypo
@ -0,0 +23,20 @@/// custom message for the changesmessage: String,#[arg(short, long, default_value = "false")]/// commit changes only to the local rempolocal: bool,#[arg(short, long, default_value = "false")]/// do not create a new commit and only sync the remote repo with the localno_save: bool,#[arg(long, default_value = "false")]/// this will ignore checks for unresolved merge conflictsallow_unresolved: bool,}impl Cmd {pub fn execute(&self) -> anyhow::Result<()> {let repo = Repository::discover(".").context("not inside a git repository")?;if !self.no_save {Doppelte Verneinung macht es bisschen unnötig schwer zu lesen als Menschen. Also vielleicht einfach das field save nennen und auf true defaulten
ich glaube ich werde das feld einfach in
--remoteumbenennen. das macht dann vielleicht auch offensichtilcher, dass es das gegenstück zu "local" ist.macht es zwar alleine betrachtet etwas ungenauer was genau die flag macht, aber da kan ich ja noch doc-types schreiben
@ -0,0 +29,20 @@#[arg(short, long, default_value = "false")]/// do not create a new commit and only sync the remote repo with the localno_save: bool,#[arg(long, default_value = "false")]/// this will ignore checks for unresolved merge conflictsallow_unresolved: bool,}impl Cmd {pub fn execute(&self) -> anyhow::Result<()> {let repo = Repository::discover(".").context("not inside a git repository")?;if !self.no_save {commit::save_changes(&repo, &self.message, self.allow_unresolved)?;}if !self.local {remote::synchronize()?;}Vielleicht macht hier noch eine message sinn wenn no save und local an sind. Weil da passiert ja nix.
good point, adde ich noch
@ -0,0 +55,20 @@use crate::command::sync::util::git_root;use anyhow::Context;use git2::Repository;use std::process::Command;pub fn save_changes(repo: &Repository,commit_message: &str,allow_unresolved: bool,) -> anyhow::Result<()> {let status = git_status::StatusReport::new(&repo)?;// error out when there are merge conflictsif !allow_unresolved {status.assume_no_conflicts()?;}let cwd = git_root()?;let add = Command::new("git").args(["add", "."])Der Punkt steht schon für "alles im aktuellem working directory". Ist das hier nötig, wenn wir eh das ganze repo adden? Wenn ja warum?
Man könnte theoretisch das adden auch im commit machen, jedoch weiß ich nicht, ob es dafür auch eine möglichkeit im
git rebasegit, das werde ich mir nochmal anschauen.Ansonsten muss das git add hier stehen bleiben.
Okay also ich habe jetzt nichts in der rebase config dafür gesehen. ich würde es deswegen mal drinn lassen
@ -0,0 +83,20 @@// This expectes, that the user does not run `sac sync` during a 'custom' rebase// but only after a `sac sync` that resulted in merge conflicts.let is_merge = util::is_rebase()?;if is_merge {// Warning: this is a dirty hack//// git rebase --continue will spawn an editor to provide the commit message// the `-c` flag overwrites this editor configuration for this single command// to be "echo 'COMMIT_MESSAGE' > "// git will invoke this command and append the file name of the commit file.// that way to COMMIT_MESSAGE will be written to said file.//// For this hack to work 'echo' and the pipe operator '>' must be valid syntax// on the users maschine, however as they are wide-spread operators this should// on most maschines™let merge = Command::new("git").args(["-c",&format!("core.editor=echo '{commit_message}' > "),"rebase",Hab mir is_rebase noch nicht angeschaut, aber wenn das wirklich wie der Variablennamen is_merge vermuten lässt auch merges umfasst: funktioniert das hier dann auch bei Leuten, die nicht als default strategy rebase sondern merge eingestellt haben?
@ -0,0 +175,20 @@pub struct StatusReport {created: Vec<String>,modified: Vec<String>,deleted: Vec<String>,merged: Vec<String>,typechange: Vec<String>,}impl StatusReport {pub fn new(repo: &Repository) -> anyhow::Result<StatusReport> {let mut status = StatusOptions::new();status.show(StatusShow::IndexAndWorkdir);status.include_untracked(true);status.include_unmodified(true);let unstaged = repo.statuses(Some(&mut status)).context("failed to list changed files")?;let mut report = StatusReport {Du kannst für StatusReport einfach #[derive(Default)] machen und dann hier StatusReport::default() nutzen. Ist ein bisschen kürzer
@ -0,0 +216,20 @@}return Ok(report);}/// Check whether all merge conflicts have been resolved/// Will error out if there are still merge conflictspub fn assume_no_conflicts(&self) -> anyhow::Result<()> {let is_rebase = util::is_rebase()?;if !is_rebase {return Ok(());}let mut msg = "Unresolved merge conflicts found in:\n".to_string();let mut had_conflicts = false;let root = util::git_root()?;'files: for file in self.created.iter().chain(self.modified.iter())Nice, progress im iter-land
@ -0,0 +282,20 @@StatusType::Typechange => &self.typechange,};if files.len() == 0 {return out;}let mut out = out + &status.header();for path in files.iter() {out += &status.file(path);}return out;}pub fn log(&self) {let out = "".to_string();let out = self.list_files(out, StatusType::Created);let out = self.list_files(out, StatusType::Modified);let out = self.list_files(out, StatusType::Merged);let out = self.list_files(out, StatusType::Deleted);let out = self.list_files(out, StatusType::Typechange);print!("{out}");Debug code?
Ne das loggen ist schon intensional.
finde es sieht eigentlich ganz hübsch aus, wenn man nochmal sieht, welche datein man gerade commited hat.
also vor allem falls man irgendwie .env files commited, dass einem das wenigstens angezeigt wird und man dann nochmal nachdenken kann, ob das gerade wirklich gewollt war...
Ahh sorry, hatte das auch ein bisschen falsch gelesen. Hatte nicht gesehen, dass du quasi das out immer weiter updatest. Dachte die variable shadowed einfach immer die vorherige
@ -0,0 +310,20 @@use spinners::{Spinner, Spinners};use std::process::Command;pub fn synchronize() -> anyhow::Result<()> {let mut sp = Spinner::new(Spinners::Line, "sync changes with remote".into());match push_changes() {Err(err) => {if let Err(err) = match_push_error(&err.to_string(), true) {sp.stop_and_persist("☓", "failed to sync with remote".into());anyhow::bail!(err);}sp.stop_and_persist(">", "remote is ahead".into());}Ok(_) => {sp.stop_and_persist("🗸", "synced changes with remote".into());return Ok(());}};// failed to push -> pull and push againBesteht practice allgemein in git ist eigentlich immer erst zu pullen. Vielleicht lohnt es sich den ersten push Versuch zu lassen und einfach immer mit pull zu starten?
@ -0,0 +348,20 @@return Ok(());}fn push_changes() -> anyhow::Result<()> {let push = Command::new("git").args(["push"]).output().context("failed to execute git")?;if !push.status.success() {anyhow::bail!(String::from_utf8(push.stderr).unwrap_or("failed to run 'git push'".into()),)}return Ok(());}fn pull_changes() -> anyhow::Result<()> {let pull = Command::new("git").args(["pull", "--rebase"])Ahh OK, du rebased immer. Solange die user nur SAC nehmen sollte es also keine normalen merges geben. Das erledigt dann einen dee vorherigen Kommentare
Ja,
sachat generell probleme wenn es mitgitzusammen genutzt wird (z.B. kann es sync nur nutzen wenn eine upstream branch definiert ist, was beisac branchpassiert, beigit branchaber nicht unbedingt).Vielleicht sollte man da nochmal irgendwo in der documentation ein verweis machen, dass es alleine genutzt werden sollte (oder halt nur wenn man weiß was man tut
b276fbfc36fdecc05eb3