tekkub-fugit 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/SciTE.properties +4 -0
- data/VERSION.yml +4 -0
- data/bin/fugit +5 -0
- data/fugit.gemspec +29 -0
- data/lib/fugit/commit.rb +98 -0
- data/lib/fugit/console.rb +33 -0
- data/lib/fugit/diff.rb +119 -0
- data/lib/fugit/icon_loader.rb +17 -0
- data/lib/fugit/index_list.rb +148 -0
- data/lib/fugit/main_frame.rb +91 -0
- data/lib/fugit/messages.rb +20 -0
- data/lib/fugit.rb +19 -0
- data/lib/icons/asterisk_yellow.png +0 -0
- data/lib/icons/disk.png +0 -0
- data/lib/icons/folder_add.png +0 -0
- data/lib/icons/folder_delete.png +0 -0
- data/lib/icons/page_add.png +0 -0
- data/lib/icons/page_delete.png +0 -0
- data/lib/icons/page_down.gif +0 -0
- data/lib/icons/page_up.gif +0 -0
- data/lib/icons/plus_minus.gif +0 -0
- data/lib/icons/script.png +0 -0
- data/lib/icons/script_add.png +0 -0
- data/lib/icons/script_delete.png +0 -0
- data/lib/icons/script_edit.png +0 -0
- data/lib/icons/text_signature.png +0 -0
- data/lib/icons/tick.png +0 -0
- metadata +82 -0
data/SciTE.properties
ADDED
data/VERSION.yml
ADDED
data/bin/fugit
ADDED
data/fugit.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{fugit}
|
3
|
+
s.version = "0.0.0"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["Tekkub"]
|
7
|
+
s.date = %q{2009-02-10}
|
8
|
+
s.default_executable = %q{fugit}
|
9
|
+
s.description = %q{A cross-platform replacement for git-gui based on wxruby}
|
10
|
+
s.email = %q{tekkub@gmail.com}
|
11
|
+
s.executables = ["fugit"]
|
12
|
+
s.files = ["fugit.gemspec", "SciTE.properties", "VERSION.yml", "bin/fugit", "lib/fugit", "lib/fugit/commit.rb", "lib/fugit/console.rb", "lib/fugit/diff.rb", "lib/fugit/icon_loader.rb", "lib/fugit/index_list.rb", "lib/fugit/main_frame.rb", "lib/fugit/messages.rb", "lib/fugit.rb", "lib/icons", "lib/icons/asterisk_yellow.png", "lib/icons/disk.png", "lib/icons/folder_add.png", "lib/icons/folder_delete.png", "lib/icons/page_add.png", "lib/icons/page_delete.png", "lib/icons/page_down.gif", "lib/icons/page_up.gif", "lib/icons/plus_minus.gif", "lib/icons/script.png", "lib/icons/script_add.png", "lib/icons/script_delete.png", "lib/icons/script_edit.png", "lib/icons/text_signature.png", "lib/icons/tick.png"]
|
13
|
+
s.has_rdoc = true
|
14
|
+
s.homepage = %q{http://github.com/tekkub/fugit}
|
15
|
+
s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubygems_version = %q{1.2.0}
|
18
|
+
s.summary = %q{TODO}
|
19
|
+
|
20
|
+
if s.respond_to? :specification_version then
|
21
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
22
|
+
s.specification_version = 2
|
23
|
+
|
24
|
+
if current_version >= 3 then
|
25
|
+
else
|
26
|
+
end
|
27
|
+
else
|
28
|
+
end
|
29
|
+
end
|
data/lib/fugit/commit.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
include Wx
|
2
|
+
include IconLoader
|
3
|
+
|
4
|
+
module Fugit
|
5
|
+
class Commit < Panel
|
6
|
+
def initialize(parent)
|
7
|
+
super(parent, ID_ANY)
|
8
|
+
|
9
|
+
@input = TextCtrl.new(self, ID_ANY, nil, nil, nil, TE_MULTILINE|TE_DONTWRAP)
|
10
|
+
@author = TextCtrl.new(self, ID_ANY)
|
11
|
+
@committer = TextCtrl.new(self, ID_ANY)
|
12
|
+
@committer.disable
|
13
|
+
|
14
|
+
@toolbar = ToolBar.new(self, ID_ANY)
|
15
|
+
@toolbar.set_tool_bitmap_size(Size.new(16,16))
|
16
|
+
@toolbar.add_tool(101, "Commit", get_icon("disk.png"), "Commit")
|
17
|
+
@toolbar.add_tool(102, "Sign off", get_icon("text_signature.png"), "Sign off")
|
18
|
+
@toolbar.add_separator
|
19
|
+
@toolbar.add_tool(103, "Push", get_icon("page_up.gif"), "Push")
|
20
|
+
@toolbar.add_tool(104, "Pull", get_icon("page_down.gif"), "Pull")
|
21
|
+
@toolbar.realize
|
22
|
+
|
23
|
+
box = BoxSizer.new(HORIZONTAL)
|
24
|
+
box.add(@committer, 1, EXPAND)
|
25
|
+
box.add(@author, 1, EXPAND)
|
26
|
+
|
27
|
+
flex = FlexGridSizer.new(2,2,0,0)
|
28
|
+
flex.add(StaticText.new(self, ID_ANY, "Committer/Author:"), 0, EXPAND)
|
29
|
+
flex.add(box, 0, EXPAND)
|
30
|
+
flex.add(StaticText.new(self, ID_ANY, "Commit message:"), 0, EXPAND)
|
31
|
+
flex.add(@input, 0, EXPAND)
|
32
|
+
flex.add_growable_row(1)
|
33
|
+
flex.add_growable_col(1)
|
34
|
+
|
35
|
+
box = BoxSizer.new(VERTICAL)
|
36
|
+
box.add(@toolbar, 0, EXPAND)
|
37
|
+
box.add_spacer(4)
|
38
|
+
box.add(flex, 1, EXPAND)
|
39
|
+
self.set_sizer(box)
|
40
|
+
|
41
|
+
evt_tool(101, :on_commit_clicked)
|
42
|
+
|
43
|
+
register_for_message(:save_clicked, :on_commit_clicked)
|
44
|
+
register_for_message(:commit_saved, :on_commit_saved)
|
45
|
+
register_for_message(:refresh, :update)
|
46
|
+
|
47
|
+
name = `git config user.name`
|
48
|
+
email = `git config user.email`
|
49
|
+
@committer.set_value("#{name.chomp} <#{email.chomp}>")
|
50
|
+
@author.set_value("#{name.chomp} <#{email.chomp}>")
|
51
|
+
end
|
52
|
+
|
53
|
+
def on_commit_clicked
|
54
|
+
msg = @input.get_value
|
55
|
+
if !has_staged_changes?
|
56
|
+
@nothing_to_commit_error ||= MessageDialog.new(self, "No changes are staged to commit.", "Commit error", OK|ICON_ERROR)
|
57
|
+
@nothing_to_commit_error.show_modal
|
58
|
+
elsif msg.empty?
|
59
|
+
@no_msg_error ||= MessageDialog.new(self, "Please enter a commit message.", "Commit error", OK|ICON_ERROR)
|
60
|
+
@no_msg_error.show_modal
|
61
|
+
else
|
62
|
+
commit_file = File.join(Dir.pwd, ".git", "fugit_commit.txt")
|
63
|
+
File.open(commit_file, "w") {|f| f << msg}
|
64
|
+
`git commit --file=.git/fugit_commit.txt --author="#{@author.get_value}"`
|
65
|
+
File.delete(commit_file)
|
66
|
+
send_message(:commit_saved)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def on_commit_saved
|
71
|
+
name = `git config user.name`
|
72
|
+
email = `git config user.email`
|
73
|
+
@author.set_value("#{name.chomp} <#{email.chomp}>")
|
74
|
+
@input.set_value("")
|
75
|
+
end
|
76
|
+
|
77
|
+
def has_staged_changes?
|
78
|
+
staged = `git ls-files --stage`
|
79
|
+
last_commit = `git ls-tree -r HEAD`
|
80
|
+
|
81
|
+
committed = {}
|
82
|
+
last_commit.split("\n").map do |line|
|
83
|
+
(info, file) = line.split("\t")
|
84
|
+
sha = info.match(/[a-f0-9]{40}/)[0]
|
85
|
+
committed[file] = sha
|
86
|
+
end
|
87
|
+
|
88
|
+
staged = staged.split("\n").map do |line|
|
89
|
+
(info, file) = line.split("\t")
|
90
|
+
sha = info.match(/[a-f0-9]{40}/)[0]
|
91
|
+
[file, sha]
|
92
|
+
end
|
93
|
+
staged.reject! {|file, sha| committed[file] == sha}
|
94
|
+
!staged.empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
include Wx
|
2
|
+
|
3
|
+
module Fugit
|
4
|
+
class Console < Panel
|
5
|
+
attr_accessor :input, :output
|
6
|
+
|
7
|
+
def initialize(parent)
|
8
|
+
super(parent, ID_ANY)
|
9
|
+
|
10
|
+
@input = TextCtrl.new(self, ID_ANY, nil, nil, Size.new(20, 20), TE_PROCESS_ENTER)
|
11
|
+
@output = TextCtrl.new(self, ID_ANY, nil, nil, Size.new(20, 20), NO_BORDER|TE_MULTILINE|TE_READONLY|TE_DONTWRAP)
|
12
|
+
|
13
|
+
box = BoxSizer.new(VERTICAL)
|
14
|
+
box.add(@output, 1, EXPAND)
|
15
|
+
box.add(@input, 0, EXPAND)
|
16
|
+
self.set_sizer(box)
|
17
|
+
|
18
|
+
evt_text_enter(@input.get_id(), :on_run_command)
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_run_command(event)
|
22
|
+
cmd = @input.get_value
|
23
|
+
begin
|
24
|
+
result = IO.popen(cmd).readlines
|
25
|
+
@output.append_text("> #{cmd}\n#{result}\n")
|
26
|
+
rescue
|
27
|
+
@output.append_text("> #{cmd}\nThere was an error running the command\n")
|
28
|
+
end
|
29
|
+
@input.clear
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
data/lib/fugit/diff.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
include Wx
|
2
|
+
|
3
|
+
module Fugit
|
4
|
+
class Diff < Panel
|
5
|
+
def initialize(parent)
|
6
|
+
super(parent, ID_ANY)
|
7
|
+
self.set_font(Font.new(8, FONTFAMILY_TELETYPE, FONTSTYLE_NORMAL, FONTWEIGHT_NORMAL))
|
8
|
+
|
9
|
+
@list = TreeCtrl.new(self, ID_ANY, nil, nil, NO_BORDER|TR_MULTIPLE|TR_HIDE_ROOT|TR_FULL_ROW_HIGHLIGHT|TR_NO_LINES)
|
10
|
+
@list.hide
|
11
|
+
|
12
|
+
@list_menu = Menu.new
|
13
|
+
@menu_stage_chunk = @list_menu.append('Stage this chunk')
|
14
|
+
evt_menu(@menu_stage_chunk, :on_menu_stage_chunk)
|
15
|
+
|
16
|
+
@text = TextCtrl.new(self, ID_ANY, nil, nil, nil, TE_MULTILINE|TE_DONTWRAP|TE_READONLY)
|
17
|
+
@text.hide
|
18
|
+
|
19
|
+
@box = BoxSizer.new(VERTICAL)
|
20
|
+
@box.add(@list, 1, EXPAND)
|
21
|
+
@box.add(@text, 1, EXPAND)
|
22
|
+
self.set_sizer(@box)
|
23
|
+
|
24
|
+
#~ evt_tree_sel_changed(@list.get_id, :on_click)
|
25
|
+
evt_tree_item_menu(@list.get_id, :on_item_menu_request)
|
26
|
+
evt_tree_item_activated(@list.get_id, :on_double_click)
|
27
|
+
|
28
|
+
register_for_message(:commit_saved, :clear)
|
29
|
+
register_for_message(:index_changed, :clear)
|
30
|
+
register_for_message(:diff_clear, :clear)
|
31
|
+
register_for_message(:diff_set, :set_diff)
|
32
|
+
register_for_message(:diff_raw, :change_value)
|
33
|
+
register_for_message(:exiting) {self.hide} # Things seem to run smoother if we hide before destruction
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_diff(value, type)
|
37
|
+
chunks = value.split("\n@@")
|
38
|
+
header = chunks.slice!(0)
|
39
|
+
chunks.map! {|line| "@@"+line}
|
40
|
+
|
41
|
+
@text.hide
|
42
|
+
@list.hide
|
43
|
+
|
44
|
+
@list.delete_all_items
|
45
|
+
root = @list.add_root("root")
|
46
|
+
chunks.each do |chunk|
|
47
|
+
diff = header + "\n" + chunk
|
48
|
+
diff = diff + "\n" if diff[-1..-1] != "\n" # git bitches if we don't have a proper newline at the end of the diff
|
49
|
+
chunk.split("\n").each do |line|
|
50
|
+
id = @list.append_item(root, line.gsub("\t", " "), -1, -1, [diff, type])
|
51
|
+
|
52
|
+
color = case line[0..0]
|
53
|
+
when "+"
|
54
|
+
Colour.new(0, 96, 0)
|
55
|
+
when "-"
|
56
|
+
Colour.new(160, 0, 0)
|
57
|
+
when "@"
|
58
|
+
Colour.new(0, 0, 150)
|
59
|
+
end
|
60
|
+
bgcolor = case line[0..0]
|
61
|
+
when "+"
|
62
|
+
Colour.new(220, 255, 220)
|
63
|
+
when "-"
|
64
|
+
Colour.new(255, 220, 220)
|
65
|
+
when "@"
|
66
|
+
Colour.new(220, 220, 225)
|
67
|
+
end
|
68
|
+
@list.set_item_text_colour(id, color) if color
|
69
|
+
@list.set_item_background_colour(id, bgcolor) if bgcolor
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
@list.show
|
74
|
+
@list.set_focus
|
75
|
+
@box.layout
|
76
|
+
end
|
77
|
+
|
78
|
+
def clear
|
79
|
+
@list.hide
|
80
|
+
@text.hide
|
81
|
+
end
|
82
|
+
|
83
|
+
def change_value(value)
|
84
|
+
@list.hide
|
85
|
+
@text.set_value(value)
|
86
|
+
@text.show
|
87
|
+
@text.set_focus
|
88
|
+
@box.layout
|
89
|
+
end
|
90
|
+
|
91
|
+
def on_item_menu_request(event)
|
92
|
+
i = event.get_item
|
93
|
+
@menu_data = nil
|
94
|
+
unless @list.get_root_item == i
|
95
|
+
@menu_data = @list.get_item_data(i)
|
96
|
+
@list_menu.set_label(@menu_stage_chunk.get_id, (@menu_data[1] == :staged ? "Unstage chunk" : "Stage chunk"))
|
97
|
+
@list.popup_menu(@list_menu)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def on_menu_stage_chunk(event)
|
102
|
+
apply_diff(*@menu_data) if @menu_data
|
103
|
+
end
|
104
|
+
|
105
|
+
def on_double_click(event)
|
106
|
+
i = event.get_item
|
107
|
+
apply_diff(*@list.get_item_data(i)) unless @list.get_root_item == i
|
108
|
+
end
|
109
|
+
|
110
|
+
def apply_diff(diff, type)
|
111
|
+
reverse = (type == :staged ? "--reverse" : "")
|
112
|
+
diff_file = File.join(Dir.pwd, ".git", "fugit_partial.diff")
|
113
|
+
File.open(diff_file, "wb") {|f| f << diff} # Write out in binary mode to preserve newlines, otherwise git freaks out
|
114
|
+
`git apply --cached #{reverse} .git/fugit_partial.diff`
|
115
|
+
File.delete(diff_file)
|
116
|
+
send_message(:index_changed)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
module IconLoader
|
3
|
+
IconBasePath = File.expand_path(File.join(File.dirname(__FILE__), "..", "icons"))
|
4
|
+
|
5
|
+
def get_icon(name, type = "png")
|
6
|
+
icon = File.join(IconBasePath, name)
|
7
|
+
case name[-3..-1].downcase
|
8
|
+
when "png"
|
9
|
+
bitmap_type = BITMAP_TYPE_PNG
|
10
|
+
else
|
11
|
+
bitmap_type = BITMAP_TYPE_GIF
|
12
|
+
end
|
13
|
+
|
14
|
+
Wx::Bitmap.new(icon, bitmap_type)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
include Wx
|
2
|
+
include IconLoader
|
3
|
+
|
4
|
+
module Fugit
|
5
|
+
class IndexList < Panel
|
6
|
+
def initialize(parent)
|
7
|
+
super(parent, ID_ANY)
|
8
|
+
|
9
|
+
@index = TreeCtrl.new(self, ID_ANY, nil, nil, NO_BORDER|TR_MULTIPLE|TR_HIDE_ROOT|TR_FULL_ROW_HIGHLIGHT|TR_NO_LINES)
|
10
|
+
|
11
|
+
imagelist = ImageList.new(16, 16)
|
12
|
+
imagelist << get_icon("asterisk_yellow.png")
|
13
|
+
imagelist << get_icon("tick.png")
|
14
|
+
imagelist << get_icon("script_add.png")
|
15
|
+
imagelist << get_icon("script_edit.png")
|
16
|
+
imagelist << get_icon("script_delete.png")
|
17
|
+
imagelist << get_icon("script.png")
|
18
|
+
@index.set_image_list(imagelist)
|
19
|
+
|
20
|
+
@toolbar = ToolBar.new(self, ID_ANY, nil, nil, TB_HORIZONTAL|NO_BORDER|TB_NODIVIDER)
|
21
|
+
@toolbar.set_tool_bitmap_size(Size.new(16,16))
|
22
|
+
@toolbar.add_tool(101, "Stage all", get_icon("folder_add.png"), "Stage all")
|
23
|
+
@toolbar.add_tool(102, "Stage", get_icon("page_add.png"), "Stage file")
|
24
|
+
@toolbar.add_separator
|
25
|
+
@toolbar.add_tool(103, "Unstage", get_icon("page_delete.png"), "Unstage file")
|
26
|
+
@toolbar.add_tool(104, "Unstage all", get_icon("folder_delete.png"), "Unstage all")
|
27
|
+
@toolbar.realize
|
28
|
+
|
29
|
+
box = BoxSizer.new(VERTICAL)
|
30
|
+
box.add(@toolbar, 0, EXPAND)
|
31
|
+
box.add(@index, 1, EXPAND)
|
32
|
+
self.set_sizer(box)
|
33
|
+
|
34
|
+
evt_tree_sel_changed(@index.get_id, :on_click)
|
35
|
+
evt_tree_item_activated(@index.get_id, :on_double_click)
|
36
|
+
|
37
|
+
evt_tree_item_collapsing(@index.get_id) {|event| event.veto}
|
38
|
+
|
39
|
+
register_for_message(:refresh, :update_tree)
|
40
|
+
register_for_message(:commit_saved, :update_tree)
|
41
|
+
register_for_message(:index_changed, :update_tree)
|
42
|
+
register_for_message(:exiting) {self.hide} # Things seem to run smoother if we hide before destruction
|
43
|
+
|
44
|
+
update_tree
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def update_tree()
|
49
|
+
self.disable
|
50
|
+
|
51
|
+
others = `git ls-files --others --exclude-standard`
|
52
|
+
deleted = `git ls-files --deleted`
|
53
|
+
modified = `git ls-files --modified`
|
54
|
+
staged = `git ls-files --stage`
|
55
|
+
last_commit = `git ls-tree -r HEAD`
|
56
|
+
|
57
|
+
committed = {}
|
58
|
+
last_commit.split("\n").map do |line|
|
59
|
+
(info, file) = line.split("\t")
|
60
|
+
sha = info.match(/[a-f0-9]{40}/)[0]
|
61
|
+
committed[file] = sha
|
62
|
+
end
|
63
|
+
|
64
|
+
deleted = deleted.split("\n")
|
65
|
+
staged = staged.split("\n").map do |line|
|
66
|
+
(info, file) = line.split("\t")
|
67
|
+
sha = info.match(/[a-f0-9]{40}/)[0]
|
68
|
+
[file, sha]
|
69
|
+
end
|
70
|
+
committed.each_pair do |file, sha|
|
71
|
+
staged << [file, ""] unless staged.assoc(file)
|
72
|
+
end
|
73
|
+
staged.reject! {|file, sha| committed[file] == sha}
|
74
|
+
|
75
|
+
@index.hide
|
76
|
+
@index.delete_all_items
|
77
|
+
root = @index.add_root("root")
|
78
|
+
uns = @index.append_item(root, "Unstaged", 0)
|
79
|
+
stg = @index.append_item(root, "Staged", 1)
|
80
|
+
|
81
|
+
others.split("\n").each {|file| @index.append_item(uns, file, 2, -1, [file, :new, :unstaged])}
|
82
|
+
modified.split("\n").each {|file| @index.append_item(uns, file, 3, -1, [file, :modified, :unstaged]) unless deleted.include?(file)}
|
83
|
+
deleted.each {|file| @index.append_item(uns, file, 4, -1, [file, :deleted, :unstaged])}
|
84
|
+
staged.each {|file, sha| @index.append_item(stg, file, 5, -1, [file, :modified, :staged])}
|
85
|
+
|
86
|
+
@index.get_root_items.each do |i|
|
87
|
+
@index.set_item_bold(i)
|
88
|
+
@index.sort_children(i)
|
89
|
+
end
|
90
|
+
|
91
|
+
@index.expand_all
|
92
|
+
@index.show
|
93
|
+
self.enable
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def on_click(event)
|
98
|
+
#~ @staged.deselect(-1) # Clear the other box's selection
|
99
|
+
|
100
|
+
i = event.get_item
|
101
|
+
return if i == 0 || !self.enabled?
|
102
|
+
|
103
|
+
if @index.get_root_items.include?(i)
|
104
|
+
send_message(:diff_clear)
|
105
|
+
else
|
106
|
+
(file, change, status) = @index.get_item_data(i)
|
107
|
+
case status
|
108
|
+
when :unstaged
|
109
|
+
case change
|
110
|
+
when :new
|
111
|
+
val = File.read(file)
|
112
|
+
send_message(:diff_raw, val)
|
113
|
+
when :modified, :deleted
|
114
|
+
val = `git diff -- #{file}`
|
115
|
+
send_message(:diff_set, val, :unstaged)
|
116
|
+
else
|
117
|
+
send_message(:diff_clear)
|
118
|
+
end
|
119
|
+
when :staged
|
120
|
+
val = `git diff --cached -- #{file}`
|
121
|
+
send_message(:diff_set, val, :staged)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def on_double_click(event)
|
128
|
+
i = event.get_item
|
129
|
+
unless @index.get_root_items.include?(i)
|
130
|
+
(file, change, status) = @index.get_item_data(i)
|
131
|
+
case status
|
132
|
+
when :unstaged
|
133
|
+
case change
|
134
|
+
when :deleted
|
135
|
+
`git rm --cached "#{file}"`
|
136
|
+
else
|
137
|
+
`git add "#{file}"`
|
138
|
+
end
|
139
|
+
when :staged
|
140
|
+
`git reset "#{file}"`
|
141
|
+
end
|
142
|
+
|
143
|
+
send_message(:index_changed)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
include Wx
|
2
|
+
include IconLoader
|
3
|
+
|
4
|
+
module Fugit
|
5
|
+
class MainFrame < Frame
|
6
|
+
attr_accessor :app_verion, :index, :commit, :diff
|
7
|
+
|
8
|
+
def initialize(title, version)
|
9
|
+
super(nil, :title => title, :size => [ 800, 600 ])
|
10
|
+
|
11
|
+
self.app_verion = version
|
12
|
+
|
13
|
+
# Set up our AUI manager
|
14
|
+
@mgr = AuiManager.new
|
15
|
+
@mgr.set_managed_window(self)
|
16
|
+
|
17
|
+
set_min_size(Size.new(400,300))
|
18
|
+
setup_panes
|
19
|
+
|
20
|
+
icon_file = File.expand_path(File.join(IconBasePath, "plus_minus.gif"))
|
21
|
+
self.icon = Icon.new(icon_file, BITMAP_TYPE_GIF)
|
22
|
+
|
23
|
+
menu_bar = MenuBar.new
|
24
|
+
|
25
|
+
# The "file" menu
|
26
|
+
menu_file = Menu.new
|
27
|
+
# Using ID_EXIT standard id means the menu item will be given the right label for the platform and language, and placed in the correct platform-specific menu - eg on OS X, in the Application's menu
|
28
|
+
menu_file.append(ID_SAVE, "&Save commit\tCtrl-S", "Save commit")
|
29
|
+
refresh = menu_file.append(ID_ANY, "&Refresh\tF5", "Refresh the index list")
|
30
|
+
menu_file.append(ID_EXIT, "E&xit", "Quit this program")
|
31
|
+
menu_bar.append(menu_file, "&File")
|
32
|
+
|
33
|
+
# The "help" menu
|
34
|
+
menu_help = Menu.new
|
35
|
+
menu_help.append(ID_ABOUT, "&About...\tF1", "Show about dialog")
|
36
|
+
menu_bar.append(menu_help, "&Help")
|
37
|
+
|
38
|
+
# Assign the menubar to this frame
|
39
|
+
self.menu_bar = menu_bar
|
40
|
+
|
41
|
+
evt_menu(ID_SAVE) {|event| send_message(:save_clicked)}
|
42
|
+
evt_menu(refresh) {|event| send_message(:refresh)}
|
43
|
+
evt_menu(ID_EXIT) {|event| close} # End the application; it should finish automatically when the last window is closed.
|
44
|
+
evt_menu(ID_ABOUT, :on_about)
|
45
|
+
evt_close() do |event|
|
46
|
+
send_message(:exiting) # Notify listeners that we're closing up shop
|
47
|
+
destroy
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
|
51
|
+
self.accelerator_table = AcceleratorTable.new(AcceleratorEntry.new(MOD_CMD, ?w, ID_EXIT))
|
52
|
+
|
53
|
+
@mgr.update
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
#####################
|
58
|
+
## Setup ##
|
59
|
+
#####################
|
60
|
+
|
61
|
+
def setup_panes
|
62
|
+
pi = AuiPaneInfo.new
|
63
|
+
size = Size.new(800, 150)
|
64
|
+
pi.bottom.set_name('commit').set_caption("Commit").set_layer(1).set_position(1).set_best_size(size).set_min_size(size).set_floating_size(size)
|
65
|
+
@commit = Commit.new(self)
|
66
|
+
@mgr.add_pane(@commit, pi)
|
67
|
+
|
68
|
+
#~ pi = AuiPaneInfo.new
|
69
|
+
#~ size = Size.new(800, 75)
|
70
|
+
#~ pi.bottom.set_name('console').set_caption("Console").set_layer(3).set_position(1).set_best_size(size).set_min_size(size).set_floating_size(size).set_maximize_button.set_minimize_button
|
71
|
+
#~ @mgr.add_pane(Console.new(self), pi)
|
72
|
+
|
73
|
+
pi = AuiPaneInfo.new
|
74
|
+
size = Size.new(200, 350)
|
75
|
+
pi.left.set_name('index').set_caption("Index").set_layer(2).set_position(1).set_best_size(size).set_min_size(size).set_floating_size(size)
|
76
|
+
@index = IndexList.new(self)
|
77
|
+
@mgr.add_pane(@index, pi)
|
78
|
+
|
79
|
+
pi = AuiPaneInfo.new
|
80
|
+
size = Size.new(200, 350)
|
81
|
+
pi.center_pane.set_name('diff')
|
82
|
+
@diff = Diff.new(self)
|
83
|
+
@mgr.add_pane(@diff, pi)
|
84
|
+
end
|
85
|
+
|
86
|
+
def on_about
|
87
|
+
Wx::about_box(:name => self.title, :version => self.app_verion, :description => "WxRuby-based git GUI", :developers => ['tekkub - http://tekkub.github.com'])
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module Wx
|
3
|
+
class EvtHandler
|
4
|
+
def register_for_message(message, method = nil, &block)
|
5
|
+
raise "Must pass method or block" unless block || method
|
6
|
+
|
7
|
+
block ||= Proc.new {|*args| self.send(method, *args)}
|
8
|
+
@@message_blocks ||= {}
|
9
|
+
@@message_blocks[message] ||= []
|
10
|
+
@@message_blocks[message] << block
|
11
|
+
end
|
12
|
+
|
13
|
+
def send_message(message, *args)
|
14
|
+
blocks = @@message_blocks[message] || []
|
15
|
+
blocks.each {|block| block.call(*args)}
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/lib/fugit.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
$:.unshift File.dirname(__FILE__)
|
3
|
+
|
4
|
+
require 'wx'
|
5
|
+
|
6
|
+
require "fugit/messages"
|
7
|
+
require "fugit/icon_loader"
|
8
|
+
require "fugit/main_frame"
|
9
|
+
require "fugit/commit"
|
10
|
+
require "fugit/console"
|
11
|
+
require "fugit/diff"
|
12
|
+
require "fugit/index_list"
|
13
|
+
|
14
|
+
|
15
|
+
Wx::App.run do
|
16
|
+
self.app_name = "Fugit"
|
17
|
+
frame = Fugit::MainFrame.new("Fugit", "0.0.1 Alpha")
|
18
|
+
frame.show
|
19
|
+
end
|
Binary file
|
data/lib/icons/disk.png
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/icons/tick.png
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tekkub-fugit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tekkub
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-10 00:00:00 -08:00
|
13
|
+
default_executable: fugit
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A cross-platform replacement for git-gui based on wxruby
|
17
|
+
email: tekkub@gmail.com
|
18
|
+
executables:
|
19
|
+
- fugit
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- fugit.gemspec
|
26
|
+
- SciTE.properties
|
27
|
+
- VERSION.yml
|
28
|
+
- bin/fugit
|
29
|
+
- lib/fugit
|
30
|
+
- lib/fugit/commit.rb
|
31
|
+
- lib/fugit/console.rb
|
32
|
+
- lib/fugit/diff.rb
|
33
|
+
- lib/fugit/icon_loader.rb
|
34
|
+
- lib/fugit/index_list.rb
|
35
|
+
- lib/fugit/main_frame.rb
|
36
|
+
- lib/fugit/messages.rb
|
37
|
+
- lib/fugit.rb
|
38
|
+
- lib/icons
|
39
|
+
- lib/icons/asterisk_yellow.png
|
40
|
+
- lib/icons/disk.png
|
41
|
+
- lib/icons/folder_add.png
|
42
|
+
- lib/icons/folder_delete.png
|
43
|
+
- lib/icons/page_add.png
|
44
|
+
- lib/icons/page_delete.png
|
45
|
+
- lib/icons/page_down.gif
|
46
|
+
- lib/icons/page_up.gif
|
47
|
+
- lib/icons/plus_minus.gif
|
48
|
+
- lib/icons/script.png
|
49
|
+
- lib/icons/script_add.png
|
50
|
+
- lib/icons/script_delete.png
|
51
|
+
- lib/icons/script_edit.png
|
52
|
+
- lib/icons/text_signature.png
|
53
|
+
- lib/icons/tick.png
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: http://github.com/tekkub/fugit
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options:
|
58
|
+
- --inline-source
|
59
|
+
- --charset=UTF-8
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.2.0
|
78
|
+
signing_key:
|
79
|
+
specification_version: 2
|
80
|
+
summary: TODO
|
81
|
+
test_files: []
|
82
|
+
|