Skip to content

Commit

Permalink
Confirm overwriting uncommitted changes on branch change (#1524)
Browse files Browse the repository at this point in the history
* Add confirm overwrite uncommitted dialog

* Include uncommitted diff in dialog

---------

Co-authored-by: Jeremy Wootten <[email protected]>
Co-authored-by: Ryan Kornheisl <[email protected]>
  • Loading branch information
3 people authored Feb 2, 2025
1 parent f77f5f5 commit 2284168
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 4 deletions.
1 change: 1 addition & 0 deletions po/POTFILES
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ src/Dialogs/GlobalSearchDialog.vala
src/Dialogs/NewBranchDialog.vala
src/Dialogs/PreferencesDialog.vala
src/Dialogs/RestoreConfirmationDialog.vala
src/Dialogs/OverwriteUncommittedConfirmationDialog.vala
src/FolderManager/File.vala
src/FolderManager/FileItem.vala
src/FolderManager/FileView.vala
Expand Down
49 changes: 49 additions & 0 deletions src/Dialogs/OverwriteUncommittedConfirmationDialog.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2025 elementary, Inc. (https://elementary.io)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 3 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

public class Scratch.Dialogs.OverwriteUncommittedConfirmationDialog : Granite.MessageDialog {

public string branch_name { get; construct; }
public OverwriteUncommittedConfirmationDialog (
Gtk.Window parent,
string new_branch_name,
string details
) {
Object (
buttons: Gtk.ButtonsType.NONE,
transient_for: parent,
branch_name: new_branch_name
);

show_error_details (details);
}

construct {
modal = true;
image_icon = new ThemedIcon ("dialog-stop");

primary_text = _("There are uncommitted changes in the current branch");
///TRANSLATORS '%s' is a placeholder for the name of the branch to be checked out
secondary_text = _("Uncommitted changes will be permanently lost if <b>'%s'</b> is checked out now.\n\n<i>It is recommended that uncommitted changes are stashed, committed, or reverted before proceeding </i>").printf (branch_name);

var proceed_button = (Gtk.Button) add_button (_("Checkout and Overwrite"), Gtk.ResponseType.ACCEPT);
proceed_button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
var cancel_button = add_button (_("Do not Checkout"), Gtk.ResponseType.REJECT);
cancel_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION);
}
}
2 changes: 1 addition & 1 deletion src/FolderManager/ProjectFolderItem.vala
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ namespace Scratch.FolderManager {
private void handle_change_branch_action (GLib.Variant? parameter) {
var branch_name = parameter.get_string ();
try {
monitored_repo.change_branch (branch_name);
monitored_repo.change_local_branch (branch_name);
} catch (GLib.Error e) {
warning ("Failed to change branch to %s. %s", branch_name, e.message);
}
Expand Down
67 changes: 64 additions & 3 deletions src/Services/MonitoredRepository.vala
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,43 @@ namespace Scratch.Services {
return true;
}

public void change_branch (string new_branch_name) throws Error {
public void change_local_branch (string new_branch_name) throws Error {
var branch = git_repo.lookup_branch (new_branch_name, Ggit.BranchType.LOCAL);
git_repo.set_head (((Ggit.Ref)branch).get_name ());
checkout_branch (branch);
}

private void checkout_branch (Ggit.Branch new_head_branch, bool confirm = true) throws Error {
if (confirm && has_uncommitted) {
confirm_checkout_branch (new_head_branch);
return;
}

git_repo.set_head (((Ggit.Ref) new_head_branch).get_name ());
var options = new Ggit.CheckoutOptions () {
//Ensure documents match checked out branch (deal with potential conflicts/losses beforehand)
strategy = Ggit.CheckoutStrategy.FORCE
};

git_repo.checkout_head (options);

branch_name = new_branch_name;
branch_name = new_head_branch.get_name ();
}

private void confirm_checkout_branch (Ggit.Branch new_head_branch) {
var parent = ((Gtk.Application)(GLib.Application.get_default ())).get_active_window ();
var dialog = new Scratch.Dialogs.OverwriteUncommittedConfirmationDialog (
parent,
new_head_branch.get_name (),
get_project_diff ()
);
dialog.response.connect ((res) => {
dialog.destroy ();
if (res == Gtk.ResponseType.ACCEPT) {
checkout_branch (new_head_branch, false);
}
});

dialog.present ();
}

public void create_new_branch (string name) throws Error {
Expand Down Expand Up @@ -264,6 +290,41 @@ namespace Scratch.Services {
return git_repo.path_is_ignored (path);
}

public string get_project_diff () throws GLib.Error {
var sb = new StringBuilder ("");
var repo_diff_list = new Ggit.Diff.index_to_workdir (git_repo, null, null);
repo_diff_list.print (Ggit.DiffFormatType.PATCH, (delta, hunk, line) => {
unowned var file_diff = delta.get_old_file ();
if (file_diff == null) {
return 0;
}

if (line != null) {
var delta_type = line.get_origin ();
string prefix = "?";
switch (delta_type) {
case Ggit.DiffLineType.ADDITION:
prefix = "+";
break;
case Ggit.DiffLineType.DELETION:
prefix = "-";
break;
case Ggit.DiffLineType.CONTEXT:
prefix = " ";
break;
default:
break;
}
//TODO Add color according to linetype
sb.append (prefix + line.get_text ());
}
return 0;
});

return sb.str;
}


private bool refreshing = false;
public void refresh_diff (string file_path, ref Gee.HashMap<int, VCStatus> line_status_map) {
if (refreshing) {
Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ code_files = files(
'Utils.vala',
'Dialogs/PreferencesDialog.vala',
'Dialogs/RestoreConfirmationDialog.vala',
'Dialogs/OverwriteUncommittedConfirmationDialog.vala',
'Dialogs/GlobalSearchDialog.vala',
'Dialogs/NewBranchDialog.vala',
'FolderManager/File.vala',
Expand Down

0 comments on commit 2284168

Please sign in to comment.