tekkub-fugit 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|