git-trip 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +21 -0
  3. data/Manifest.txt +89 -0
  4. data/README.txt +60 -0
  5. data/Rakefile +31 -0
  6. data/bin/git-trip +0 -0
  7. data/doc/USAGE.txt +54 -0
  8. data/lib/core_ext/hash.rb +15 -0
  9. data/lib/git-trip.rb +23 -0
  10. data/lib/git-trip/errors.rb +22 -0
  11. data/lib/git-trip/gitter.rb +10 -0
  12. data/lib/git-trip/gitter/base.rb +18 -0
  13. data/lib/git-trip/gitter/dir.rb +32 -0
  14. data/lib/git-trip/gitter/uri.rb +40 -0
  15. data/lib/git-trip/paint_mode.rb +52 -0
  16. data/lib/git-trip/painter.rb +167 -0
  17. data/spec/core_ext/hash_spec.rb +25 -0
  18. data/spec/git-trip/errors_spec.rb +43 -0
  19. data/spec/git-trip/gitter/base_spec.rb +15 -0
  20. data/spec/git-trip/gitter/dir_spec.rb +37 -0
  21. data/spec/git-trip/gitter/uri_spec.rb +25 -0
  22. data/spec/git-trip/gitter_spec.rb +11 -0
  23. data/spec/git-trip/paint_mode_spec.rb +56 -0
  24. data/spec/git-trip/painter_spec.rb +173 -0
  25. data/spec/git_trip_spec.rb +23 -0
  26. data/spec/rcov.opts +1 -0
  27. data/spec/spec.opts +4 -0
  28. data/spec/spec_helper.rb +15 -0
  29. data/tasks/ditz.rake +42 -0
  30. data/tasks/docs.rake +68 -0
  31. data/tasks/gittrip.rake +63 -0
  32. data/tasks/rspec.rake +22 -0
  33. data/tasks/site.rake +48 -0
  34. data/tasks/util.rake +44 -0
  35. data/vendor/grit/History.txt +6 -0
  36. data/vendor/grit/Manifest.txt +53 -0
  37. data/vendor/grit/README.txt +213 -0
  38. data/vendor/grit/Rakefile +29 -0
  39. data/vendor/grit/grit.gemspec +16 -0
  40. data/vendor/grit/lib/grit.rb +37 -0
  41. data/vendor/grit/lib/grit/actor.rb +36 -0
  42. data/vendor/grit/lib/grit/blob.rb +117 -0
  43. data/vendor/grit/lib/grit/commit.rb +208 -0
  44. data/vendor/grit/lib/grit/config.rb +44 -0
  45. data/vendor/grit/lib/grit/diff.rb +70 -0
  46. data/vendor/grit/lib/grit/errors.rb +7 -0
  47. data/vendor/grit/lib/grit/git.rb +116 -0
  48. data/vendor/grit/lib/grit/index.rb +77 -0
  49. data/vendor/grit/lib/grit/lazy.rb +31 -0
  50. data/vendor/grit/lib/grit/ref.rb +110 -0
  51. data/vendor/grit/lib/grit/repo.rb +318 -0
  52. data/vendor/grit/lib/grit/tree.rb +99 -0
  53. data/vendor/grit/test/fixtures/blame +131 -0
  54. data/vendor/grit/test/fixtures/cat_file_blob +1 -0
  55. data/vendor/grit/test/fixtures/cat_file_blob_size +1 -0
  56. data/vendor/grit/test/fixtures/diff_2 +54 -0
  57. data/vendor/grit/test/fixtures/diff_2f +19 -0
  58. data/vendor/grit/test/fixtures/diff_f +15 -0
  59. data/vendor/grit/test/fixtures/diff_i +201 -0
  60. data/vendor/grit/test/fixtures/diff_mode_only +1152 -0
  61. data/vendor/grit/test/fixtures/diff_new_mode +17 -0
  62. data/vendor/grit/test/fixtures/diff_p +610 -0
  63. data/vendor/grit/test/fixtures/for_each_ref +0 -0
  64. data/vendor/grit/test/fixtures/for_each_ref_remotes +0 -0
  65. data/vendor/grit/test/fixtures/for_each_ref_tags +0 -0
  66. data/vendor/grit/test/fixtures/ls_tree_a +7 -0
  67. data/vendor/grit/test/fixtures/ls_tree_b +2 -0
  68. data/vendor/grit/test/fixtures/ls_tree_commit +3 -0
  69. data/vendor/grit/test/fixtures/rev_list +26 -0
  70. data/vendor/grit/test/fixtures/rev_list_count +655 -0
  71. data/vendor/grit/test/fixtures/rev_list_single +7 -0
  72. data/vendor/grit/test/fixtures/rev_parse +1 -0
  73. data/vendor/grit/test/fixtures/show_empty_commit +6 -0
  74. data/vendor/grit/test/fixtures/simple_config +2 -0
  75. data/vendor/grit/test/helper.rb +17 -0
  76. data/vendor/grit/test/profile.rb +21 -0
  77. data/vendor/grit/test/suite.rb +6 -0
  78. data/vendor/grit/test/test_actor.rb +35 -0
  79. data/vendor/grit/test/test_blob.rb +74 -0
  80. data/vendor/grit/test/test_commit.rb +182 -0
  81. data/vendor/grit/test/test_config.rb +58 -0
  82. data/vendor/grit/test/test_diff.rb +18 -0
  83. data/vendor/grit/test/test_git.rb +52 -0
  84. data/vendor/grit/test/test_head.rb +22 -0
  85. data/vendor/grit/test/test_real.rb +19 -0
  86. data/vendor/grit/test/test_reality.rb +17 -0
  87. data/vendor/grit/test/test_remote.rb +15 -0
  88. data/vendor/grit/test/test_repo.rb +278 -0
  89. data/vendor/grit/test/test_tag.rb +29 -0
  90. data/vendor/grit/test/test_tree.rb +91 -0
  91. metadata +179 -0
  92. metadata.gz.sig +0 -0
@@ -0,0 +1,44 @@
1
+ module Grit
2
+
3
+ class Config
4
+ def initialize(repo)
5
+ @repo = repo
6
+ end
7
+
8
+ def []=(key, value)
9
+ @repo.git.config({}, key, value)
10
+ @data = nil
11
+ end
12
+
13
+ def [](key)
14
+ data[key]
15
+ end
16
+
17
+ def fetch(key, default = nil)
18
+ data[key] || default || raise(IndexError.new("key not found"))
19
+ end
20
+
21
+ def keys
22
+ data.keys
23
+ end
24
+
25
+ protected
26
+ def data
27
+ @data ||= load_config
28
+ end
29
+
30
+ def load_config
31
+ hash = {}
32
+ config_lines.map do |line|
33
+ key, value = line.split(/=/, 2)
34
+ hash[key] = value
35
+ end
36
+ hash
37
+ end
38
+
39
+ def config_lines
40
+ @repo.git.config(:list => true).split(/\n/)
41
+ end
42
+ end # Config
43
+
44
+ end # Grit
@@ -0,0 +1,70 @@
1
+ module Grit
2
+
3
+ class Diff
4
+ attr_reader :a_path, :b_path
5
+ attr_reader :a_commit, :b_commit
6
+ attr_reader :a_mode, :b_mode
7
+ attr_reader :new_file, :deleted_file
8
+ attr_reader :diff
9
+
10
+ def initialize(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)
11
+ @repo = repo
12
+ @a_path = a_path
13
+ @b_path = b_path
14
+ @a_commit = a_commit =~ /^0{40}$/ ? nil : Commit.create(repo, :id => a_commit)
15
+ @b_commit = b_commit =~ /^0{40}$/ ? nil : Commit.create(repo, :id => b_commit)
16
+ @a_mode = a_mode
17
+ @b_mode = b_mode
18
+ @new_file = new_file
19
+ @deleted_file = deleted_file
20
+ @diff = diff
21
+ end
22
+
23
+ def self.list_from_string(repo, text)
24
+ lines = text.split("\n")
25
+
26
+ diffs = []
27
+
28
+ while !lines.empty?
29
+ m, a_path, b_path = *lines.shift.match(%r{^diff --git a/(.+?) b/(.+)$})
30
+
31
+ if lines.first =~ /^old mode/
32
+ m, a_mode = *lines.shift.match(/^old mode (\d+)/)
33
+ m, b_mode = *lines.shift.match(/^new mode (\d+)/)
34
+ end
35
+
36
+ if lines.empty? || lines.first =~ /^diff --git/
37
+ diffs << Diff.new(repo, a_path, b_path, nil, nil, a_mode, b_mode, false, false, nil)
38
+ next
39
+ end
40
+
41
+ new_file = false
42
+ deleted_file = false
43
+
44
+ if lines.first =~ /^new file/
45
+ m, b_mode = lines.shift.match(/^new file mode (.+)$/)
46
+ a_mode = nil
47
+ new_file = true
48
+ elsif lines.first =~ /^deleted file/
49
+ m, a_mode = lines.shift.match(/^deleted file mode (.+)$/)
50
+ b_mode = nil
51
+ deleted_file = true
52
+ end
53
+
54
+ m, a_commit, b_commit, b_mode = *lines.shift.match(%r{^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$})
55
+ b_mode.strip! if b_mode
56
+
57
+ diff_lines = []
58
+ while lines.first && lines.first !~ /^diff/
59
+ diff_lines << lines.shift
60
+ end
61
+ diff = diff_lines.join("\n")
62
+
63
+ diffs << Diff.new(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)
64
+ end
65
+
66
+ diffs
67
+ end
68
+ end # Diff
69
+
70
+ end # Grit
@@ -0,0 +1,7 @@
1
+ module Grit
2
+ class InvalidGitRepositoryError < StandardError
3
+ end
4
+
5
+ class NoSuchPathError < StandardError
6
+ end
7
+ end
@@ -0,0 +1,116 @@
1
+ trap("CHLD") do
2
+ begin
3
+ Process.wait(-1, Process::WNOHANG)
4
+ rescue Object
5
+ end
6
+ end
7
+
8
+ module Grit
9
+
10
+ class Git
11
+ class GitTimeout < RuntimeError
12
+ attr_reader :command, :bytes_read
13
+
14
+ def initialize(command = nil, bytes_read = nil)
15
+ @command = command
16
+ @bytes_read = bytes_read
17
+ end
18
+ end
19
+
20
+ undef_method :clone
21
+
22
+ class << self
23
+ attr_accessor :git_binary, :git_timeout
24
+ end
25
+
26
+ self.git_binary = "/usr/bin/env git"
27
+ self.git_timeout = 5
28
+
29
+ attr_accessor :git_dir, :bytes_read
30
+
31
+ def initialize(git_dir)
32
+ self.git_dir = git_dir
33
+ self.bytes_read = 0
34
+ end
35
+
36
+ # Run the given git command with the specified arguments and return
37
+ # the result as a String
38
+ # +cmd+ is the command
39
+ # +options+ is a hash of Ruby style options
40
+ # +args+ is the list of arguments (to be joined by spaces)
41
+ #
42
+ # Examples
43
+ # git.rev_list({:max_count => 10, :header => true}, "master")
44
+ #
45
+ # Returns String
46
+ def method_missing(cmd, options = {}, *args)
47
+ run('', cmd, '', options, args)
48
+ end
49
+
50
+ def run(prefix, cmd, postfix, options, args)
51
+ timeout = options.delete(:timeout)
52
+ timeout = true if timeout.nil?
53
+
54
+ opt_args = transform_options(options)
55
+ ext_args = args.map { |a| a == '--' ? a : "'#{a}'" }
56
+
57
+ call = "#{prefix}#{Git.git_binary} --git-dir='#{self.git_dir}' #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{postfix}"
58
+ puts call if Grit.debug
59
+ response = timeout ? sh(call) : wild_sh(call)
60
+ puts response if Grit.debug
61
+ response
62
+ end
63
+
64
+ def sh(command)
65
+ pid, _, io, _ = Open4.popen4(command)
66
+ ret = Timeout.timeout(self.class.git_timeout) { io.read }
67
+ @bytes_read += ret.size
68
+
69
+ if @bytes_read > 5242880 # 5.megabytes
70
+ bytes = @bytes_read
71
+ @bytes_read = 0
72
+ raise GitTimeout.new(command, bytes)
73
+ end
74
+
75
+ ret
76
+ rescue Object => e
77
+ Process.kill('KILL', pid) rescue nil
78
+ bytes = @bytes_read
79
+ @bytes_read = 0
80
+ raise GitTimeout.new(command, bytes)
81
+ end
82
+
83
+ def wild_sh(command)
84
+ pid, _, io, _ = Open4.popen4(command)
85
+ io.read
86
+ end
87
+
88
+ # Transform Ruby style options into git command line options
89
+ # +options+ is a hash of Ruby style options
90
+ #
91
+ # Returns String[]
92
+ # e.g. ["--max-count=10", "--header"]
93
+ def transform_options(options)
94
+ args = []
95
+ options.keys.each do |opt|
96
+ if opt.to_s.size == 1
97
+ if options[opt] == true
98
+ args << "-#{opt}"
99
+ else
100
+ val = options.delete(opt)
101
+ args << "-#{opt.to_s} '#{val}'"
102
+ end
103
+ else
104
+ if options[opt] == true
105
+ args << "--#{opt.to_s.gsub(/_/, '-')}"
106
+ else
107
+ val = options.delete(opt)
108
+ args << "--#{opt.to_s.gsub(/_/, '-')}='#{val}'"
109
+ end
110
+ end
111
+ end
112
+ args
113
+ end
114
+ end # Git
115
+
116
+ end # Grit
@@ -0,0 +1,77 @@
1
+ module Grit
2
+
3
+ class Index
4
+ attr_accessor :repo, :tree
5
+
6
+ def initialize(repo)
7
+ self.repo = repo
8
+ self.tree = {}
9
+ end
10
+
11
+ # Add a file to the index
12
+ # +path+ is the path (including filename)
13
+ # +data+ is the binary contents of the file
14
+ #
15
+ # Returns nothing
16
+ def add(file_path, data)
17
+ path = file_path.split('/')
18
+ filename = path.pop
19
+
20
+ current = self.tree
21
+
22
+ path.each do |dir|
23
+ current[dir] ||= {}
24
+ node = current[dir]
25
+ current = node
26
+ end
27
+
28
+ current[filename] = data
29
+ end
30
+
31
+ # Commit the contents of the index
32
+ # +message+ is the commit message
33
+ #
34
+ # Returns a String of the SHA1 of the commit
35
+ def commit(message)
36
+ tree_sha1 = write_tree(self.tree)
37
+
38
+ message = message.gsub("'", "\\'")
39
+ commit_sha1 = self.repo.git.run("echo '#{message}' | ", :commit_tree, '', {}, [tree_sha1])
40
+
41
+ # self.repo.git.update_ref({}, 'HEAD', commit_sha1)
42
+ File.open(File.join(self.repo.path, 'refs', 'heads', 'master'), 'w') do |f|
43
+ f.write(commit_sha1)
44
+ end
45
+
46
+ commit_sha1
47
+ end
48
+
49
+ # Recursively write a tree to the index
50
+ # +tree+ is the tree
51
+ #
52
+ # Returns the SHA1 String of the tree
53
+ def write_tree(tree)
54
+ lstree = []
55
+ tree.each do |k, v|
56
+ case v
57
+ when String:
58
+ lstree << "100644 blob #{write_blob(v)}\t#{k}"
59
+ when Hash:
60
+ lstree << "040000 tree #{write_tree(v)}\t#{k}"
61
+ end
62
+ end
63
+
64
+ lstree_string = lstree.join("\n").gsub("'", "\\'")
65
+ self.repo.git.run("echo '#{lstree_string}' | ", :mktree, '', {}, []).chomp
66
+ end
67
+
68
+ # Write the blob to the index
69
+ # +data+ is the data to write
70
+ #
71
+ # Returns the SHA1 String of the blob
72
+ def write_blob(data)
73
+ self.repo.git.run("echo '#{data}' | ", :hash_object, '', {:w => true, :stdin => true}, []).chomp
74
+ end
75
+ end # Index
76
+
77
+ end # Grit
@@ -0,0 +1,31 @@
1
+ ##
2
+ # Allows attributes to be declared as lazy, meaning that they won't be
3
+ # computed until they are asked for.
4
+ #
5
+ # Works by delegating each lazy_reader to a cached lazy_source method.
6
+ #
7
+ # class Person
8
+ # lazy_reader :eyes
9
+ #
10
+ # def lazy_source
11
+ # OpenStruct.new(:eyes => 2)
12
+ # end
13
+ # end
14
+ #
15
+ # >> Person.new.eyes
16
+ # => 2
17
+ #
18
+ module Lazy
19
+ def lazy_reader(*args)
20
+ args.each do |arg|
21
+ ivar = "@#{arg}"
22
+ define_method(arg) do
23
+ val = instance_variable_get(ivar)
24
+ return val if val
25
+ instance_variable_set(ivar, (@lazy_source ||= lazy_source).send(arg))
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ Object.extend Lazy unless Object.ancestors.include? Lazy
@@ -0,0 +1,110 @@
1
+ module Grit
2
+
3
+ class Ref
4
+
5
+ class << self
6
+
7
+ # Find all Refs
8
+ # +repo+ is the Repo
9
+ # +options+ is a Hash of options
10
+ #
11
+ # Returns Grit::Ref[] (baked)
12
+ def find_all(repo, options = {})
13
+ default_options = {:sort => "committerdate",
14
+ :format => "%(refname)%00%(objectname)"}
15
+
16
+ actual_options = default_options.merge(options)
17
+
18
+ output = repo.git.for_each_ref(actual_options, prefix)
19
+
20
+ self.list_from_string(repo, output)
21
+ end
22
+
23
+ # Parse out ref information into an array of baked refs objects
24
+ # +repo+ is the Repo
25
+ # +text+ is the text output from the git command
26
+ #
27
+ # Returns Grit::Ref[] (baked)
28
+ def list_from_string(repo, text)
29
+ refs = []
30
+
31
+ text.split("\n").each do |line|
32
+ refs << self.from_string(repo, line)
33
+ end
34
+
35
+ refs.sort { | x, y | x.name <=> y.name }
36
+ end
37
+
38
+ # Create a new Ref instance from the given string.
39
+ # +repo+ is the Repo
40
+ # +line+ is the formatted head information
41
+ #
42
+ # Format
43
+ # name: [a-zA-Z_/]+
44
+ # <null byte>
45
+ # id: [0-9A-Fa-f]{40}
46
+ #
47
+ # Returns Grit::Ref (baked)
48
+ def from_string(repo, line)
49
+ full_name, id = line.split("\0")
50
+ name = full_name.sub("#{prefix}/", '')
51
+ commit = Commit.create(repo, :id => id)
52
+ self.new(name, commit)
53
+ end
54
+
55
+ protected
56
+
57
+ def prefix
58
+ "refs/#{name.to_s.gsub(/^.*::/, '').downcase}s"
59
+ end
60
+
61
+ end
62
+
63
+ attr_reader :name
64
+ attr_reader :commit
65
+
66
+ # Instantiate a new Head
67
+ # +name+ is the name of the head
68
+ # +commit+ is the Commit that the head points to
69
+ #
70
+ # Returns Grit::Head (baked)
71
+ def initialize(name, commit)
72
+ @name = name
73
+ @commit = commit
74
+ end
75
+
76
+ # Pretty object inspection
77
+ def inspect
78
+ %Q{#<#{self.class.name} "#{@name}">}
79
+ end
80
+ end # Ref
81
+
82
+ # A Head is a named reference to a Commit. Every Head instance contains a name
83
+ # and a Commit object.
84
+ #
85
+ # r = Grit::Repo.new("/path/to/repo")
86
+ # h = r.heads.first
87
+ # h.name # => "master"
88
+ # h.commit # => #<Grit::Commit "1c09f116cbc2cb4100fb6935bb162daa4723f455">
89
+ # h.commit.id # => "1c09f116cbc2cb4100fb6935bb162daa4723f455"
90
+ class Head < Ref
91
+
92
+ # Get the HEAD revision of the repo.
93
+ # +repo+ is the Repo
94
+ # +options+ is a Hash of options
95
+ #
96
+ # Returns Grit::Head (baked)
97
+ def self.current(repo, options = {})
98
+ head = File.open(File.join(repo.path, 'HEAD')).read.chomp
99
+ if /ref: refs\/heads\/(.*)/.match(head)
100
+ self.new($1, repo.git.rev_parse(options, 'HEAD'))
101
+ end
102
+ end
103
+
104
+ end # Head
105
+
106
+ class Tag < Ref ; end
107
+
108
+ class Remote < Ref ; end
109
+
110
+ end # Grit