[gitg/wip/patch-stage] Implement patchset staging
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gitg/wip/patch-stage] Implement patchset staging
- Date: Wed, 1 Jan 2014 17:33:56 +0000 (UTC)
commit 1cd1276efb4a69c8c03628c934be7b8252bf98ab
Author: Jesse van den Kieboom <jessevdk gmail com>
Date: Wed Jan 1 18:33:20 2014 +0100
Implement patchset staging
gitg/commit/gitg-commit.vala | 34 +++++++++++++++++
libgitg/gitg-stage.vala | 85 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 118 insertions(+), 1 deletions(-)
---
diff --git a/gitg/commit/gitg-commit.vala b/gitg/commit/gitg-commit.vala
index 2bbc76d..3744a3f 100644
--- a/gitg/commit/gitg-commit.vala
+++ b/gitg/commit/gitg-commit.vala
@@ -733,6 +733,36 @@ namespace GitgCommit
}
}
+ private async void stage_selection() throws Error
+ {
+ var selection = yield d_main.diff_view.get_selection();
+ var stage = application.repository.stage;
+
+ foreach (var pset in selection)
+ {
+ yield stage.stage_patch(pset);
+ }
+ }
+
+ private void on_stage_clicked()
+ {
+ stage_selection.begin((obj, res) => {
+ try
+ {
+ stage_selection.end(res);
+ }
+ catch (Error e)
+ {
+ var msg = _("Failed to stage selection");
+ application.show_infobar(msg, e.message, Gtk.MessageType.ERROR);
+
+ return;
+ }
+
+ reload();
+ });
+ }
+
private void build_ui()
{
d_main = new Paned();
@@ -745,6 +775,10 @@ namespace GitgCommit
on_commit_clicked();
});
+ d_main.button_stage.clicked.connect(() => {
+ on_stage_clicked();
+ });
+
d_main.diff_view.bind_property("has-selection",
d_main.button_stage,
"sensitive",
diff --git a/libgitg/gitg-stage.vala b/libgitg/gitg-stage.vala
index 91377d4..6ae2f22 100644
--- a/libgitg/gitg-stage.vala
+++ b/libgitg/gitg-stage.vala
@@ -33,7 +33,8 @@ public errordomain StageError
{
PRE_COMMIT_HOOK_FAILED,
COMMIT_MSG_HOOK_FAILED,
- NOTHING_TO_COMMIT
+ NOTHING_TO_COMMIT,
+ INDEX_ENTRY_NOT_FOUND
}
public class PatchSet
@@ -572,6 +573,88 @@ public class Stage : Object
}
/**
+ * Stage a patch to the index.
+ *
+ * @param patch the patch to stage.
+ *
+ * Stage a provided patch to the index. The patch should contain changes
+ * of the file in the current working directory to the contents of the
+ * index (i.e. as obtained from diff_workdir)
+ */
+ public async void stage_patch(PatchSet patch) throws Error
+ {
+ // new file is the current file in the working directory
+ var newf = d_repository.get_workdir().resolve_relative_path(patch.filename);
+ var new_stream = yield newf.read_async();
+
+ yield thread_index((index) => {
+ var entries = index.get_entries();
+ var entry = entries.get_by_path(newf, 0);
+
+ if (entry == null)
+ {
+ throw new StageError.INDEX_ENTRY_NOT_FOUND(patch.filename);
+ }
+
+ var old_blob = d_repository.lookup<Ggit.Blob>(entry.get_id());
+ unowned uchar[] old_content = old_blob.get_raw_content();
+
+ var patched_stream = d_repository.create_blob();
+
+ size_t oldptr = 0;
+ size_t newptr = 0;
+
+ // Copy old_content to patched_stream while applying patches as
+ // specified in patch.patches from new_stream
+ foreach (var p in patch.patches)
+ {
+ if (p.old_offset != oldptr)
+ {
+ patched_stream.write(old_content[oldptr:p.old_offset]);
+ oldptr = p.old_offset;
+ }
+
+ if (p.type == PatchSet.Type.REMOVE)
+ {
+ oldptr += p.length;
+ }
+ else
+ {
+ // Copy in from new_stream
+ if (newptr != p.new_offset)
+ {
+ new_stream.seek(p.new_offset, SeekType.SET);
+ }
+
+ var buf = new uint8[p.length];
+
+ new_stream.read_all(buf, null);
+ patched_stream.write_all(buf, null);
+
+ newptr = p.new_offset + p.length;
+ }
+ }
+
+ // Copy remaining part of old
+ if (oldptr != old_content.length)
+ {
+ patched_stream.write_all(old_content[oldptr:old_content.length], null);
+ }
+
+ new_stream.close();
+ patched_stream.close();
+
+ var new_id = patched_stream.get_id();
+
+ var new_entry = d_repository.create_index_entry_for_path(patch.filename,
+ new_id);
+
+ index.add(new_entry);
+ index.write();
+ });
+ }
+
+ /**
* Unstage a file from the index.
*
* @param file the file to unstage.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]