jit 0.0.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE.txt +674 -0
  3. data/bin/jit +21 -0
  4. data/lib/color.rb +32 -0
  5. data/lib/command.rb +62 -0
  6. data/lib/command/add.rb +65 -0
  7. data/lib/command/base.rb +92 -0
  8. data/lib/command/branch.rb +199 -0
  9. data/lib/command/checkout.rb +104 -0
  10. data/lib/command/cherry_pick.rb +51 -0
  11. data/lib/command/commit.rb +86 -0
  12. data/lib/command/config.rb +126 -0
  13. data/lib/command/diff.rb +114 -0
  14. data/lib/command/fetch.rb +116 -0
  15. data/lib/command/init.rb +41 -0
  16. data/lib/command/log.rb +188 -0
  17. data/lib/command/merge.rb +148 -0
  18. data/lib/command/push.rb +172 -0
  19. data/lib/command/receive_pack.rb +92 -0
  20. data/lib/command/remote.rb +55 -0
  21. data/lib/command/reset.rb +64 -0
  22. data/lib/command/rev_list.rb +33 -0
  23. data/lib/command/revert.rb +69 -0
  24. data/lib/command/rm.rb +105 -0
  25. data/lib/command/shared/fast_forward.rb +19 -0
  26. data/lib/command/shared/print_diff.rb +116 -0
  27. data/lib/command/shared/receive_objects.rb +37 -0
  28. data/lib/command/shared/remote_agent.rb +44 -0
  29. data/lib/command/shared/remote_client.rb +82 -0
  30. data/lib/command/shared/send_objects.rb +24 -0
  31. data/lib/command/shared/sequencing.rb +146 -0
  32. data/lib/command/shared/write_commit.rb +167 -0
  33. data/lib/command/status.rb +210 -0
  34. data/lib/command/upload_pack.rb +54 -0
  35. data/lib/config.rb +240 -0
  36. data/lib/config/stack.rb +42 -0
  37. data/lib/database.rb +112 -0
  38. data/lib/database/author.rb +27 -0
  39. data/lib/database/backends.rb +57 -0
  40. data/lib/database/blob.rb +24 -0
  41. data/lib/database/commit.rb +70 -0
  42. data/lib/database/entry.rb +7 -0
  43. data/lib/database/loose.rb +70 -0
  44. data/lib/database/packed.rb +75 -0
  45. data/lib/database/tree.rb +77 -0
  46. data/lib/database/tree_diff.rb +88 -0
  47. data/lib/diff.rb +46 -0
  48. data/lib/diff/combined.rb +72 -0
  49. data/lib/diff/hunk.rb +64 -0
  50. data/lib/diff/myers.rb +90 -0
  51. data/lib/editor.rb +59 -0
  52. data/lib/index.rb +212 -0
  53. data/lib/index/checksum.rb +44 -0
  54. data/lib/index/entry.rb +91 -0
  55. data/lib/lockfile.rb +55 -0
  56. data/lib/merge/bases.rb +38 -0
  57. data/lib/merge/common_ancestors.rb +77 -0
  58. data/lib/merge/diff3.rb +156 -0
  59. data/lib/merge/inputs.rb +42 -0
  60. data/lib/merge/resolve.rb +178 -0
  61. data/lib/pack.rb +45 -0
  62. data/lib/pack/compressor.rb +83 -0
  63. data/lib/pack/delta.rb +58 -0
  64. data/lib/pack/entry.rb +54 -0
  65. data/lib/pack/expander.rb +54 -0
  66. data/lib/pack/index.rb +100 -0
  67. data/lib/pack/indexer.rb +200 -0
  68. data/lib/pack/numbers.rb +79 -0
  69. data/lib/pack/reader.rb +98 -0
  70. data/lib/pack/stream.rb +80 -0
  71. data/lib/pack/unpacker.rb +62 -0
  72. data/lib/pack/window.rb +47 -0
  73. data/lib/pack/writer.rb +92 -0
  74. data/lib/pack/xdelta.rb +118 -0
  75. data/lib/pager.rb +24 -0
  76. data/lib/progress.rb +78 -0
  77. data/lib/refs.rb +260 -0
  78. data/lib/remotes.rb +82 -0
  79. data/lib/remotes/protocol.rb +82 -0
  80. data/lib/remotes/refspec.rb +70 -0
  81. data/lib/remotes/remote.rb +57 -0
  82. data/lib/repository.rb +64 -0
  83. data/lib/repository/divergence.rb +21 -0
  84. data/lib/repository/hard_reset.rb +35 -0
  85. data/lib/repository/inspector.rb +49 -0
  86. data/lib/repository/migration.rb +168 -0
  87. data/lib/repository/pending_commit.rb +60 -0
  88. data/lib/repository/sequencer.rb +118 -0
  89. data/lib/repository/status.rb +98 -0
  90. data/lib/rev_list.rb +244 -0
  91. data/lib/revision.rb +155 -0
  92. data/lib/sorted_hash.rb +17 -0
  93. data/lib/temp_file.rb +34 -0
  94. data/lib/workspace.rb +107 -0
  95. metadata +103 -9
@@ -0,0 +1,42 @@
1
+ require "pathname"
2
+ require_relative "../config"
3
+
4
+ class Config
5
+ class Stack
6
+
7
+ GLOBAL_CONFIG = File.expand_path("~/.gitconfig")
8
+ SYSTEM_CONFIG = "/etc/gitconfig"
9
+
10
+ def initialize(git_path)
11
+ @configs = {
12
+ :local => Config.new(git_path.join("config")),
13
+ :global => Config.new(Pathname.new(GLOBAL_CONFIG)),
14
+ :system => Config.new(Pathname.new(SYSTEM_CONFIG))
15
+ }
16
+ end
17
+
18
+ def file(name)
19
+ if @configs.has_key?(name)
20
+ @configs[name]
21
+ else
22
+ Config.new(Pathname.new(name))
23
+ end
24
+ end
25
+
26
+ def open
27
+ @configs.each_value(&:open)
28
+ end
29
+
30
+ def get(key)
31
+ get_all(key).last
32
+ end
33
+
34
+ def get_all(key)
35
+ [:system, :global, :local].flat_map do |name|
36
+ @configs[name].open
37
+ @configs[name].get_all(key)
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,112 @@
1
+ require "digest/sha1"
2
+ require "forwardable"
3
+ require "pathname"
4
+ require "strscan"
5
+
6
+ require_relative "./database/author"
7
+ require_relative "./database/blob"
8
+ require_relative "./database/commit"
9
+ require_relative "./database/entry"
10
+ require_relative "./database/tree"
11
+ require_relative "./database/tree_diff"
12
+
13
+ require_relative "./database/backends"
14
+
15
+ class Database
16
+ TYPES = {
17
+ "blob" => Blob,
18
+ "tree" => Tree,
19
+ "commit" => Commit
20
+ }
21
+
22
+ Raw = Struct.new(:type, :size, :data)
23
+
24
+ extend Forwardable
25
+ def_delegators :@backend, :has?, :load_info, :load_raw,
26
+ :prefix_match, :pack_path
27
+
28
+ def initialize(pathname)
29
+ @objects = {}
30
+ @backend = Backends.new(pathname)
31
+ end
32
+
33
+ def store(object)
34
+ content = serialize_object(object)
35
+ object.oid = hash_content(content)
36
+
37
+ @backend.write_object(object.oid, content)
38
+ end
39
+
40
+ def hash_object(object)
41
+ hash_content(serialize_object(object))
42
+ end
43
+
44
+ def load(oid)
45
+ @objects[oid] ||= read_object(oid)
46
+ end
47
+
48
+ def load_tree_entry(oid, pathname)
49
+ commit = load(oid)
50
+ root = Database::Entry.new(commit.tree, Tree::TREE_MODE)
51
+
52
+ return root unless pathname
53
+
54
+ pathname.each_filename.reduce(root) do |entry, name|
55
+ entry ? load(entry.oid).entries[name] : nil
56
+ end
57
+ end
58
+
59
+ def load_tree_list(oid, pathname = nil)
60
+ return {} unless oid
61
+
62
+ entry = load_tree_entry(oid, pathname)
63
+ list = {}
64
+
65
+ build_list(list, entry, pathname || Pathname.new(""))
66
+ list
67
+ end
68
+
69
+ def build_list(list, entry, prefix)
70
+ return unless entry
71
+ return list[prefix.to_s] = entry unless entry.tree?
72
+
73
+ load(entry.oid).each_entry do |name, item|
74
+ build_list(list, item, prefix.join(name))
75
+ end
76
+ end
77
+
78
+ def tree_entry(oid)
79
+ Entry.new(oid, Tree::TREE_MODE)
80
+ end
81
+
82
+ def short_oid(oid)
83
+ oid[0..6]
84
+ end
85
+
86
+ def tree_diff(a, b, prune = [])
87
+ diff = TreeDiff.new(self, prune)
88
+ diff.compare_oids(a, b)
89
+ diff.changes
90
+ end
91
+
92
+ private
93
+
94
+ def serialize_object(object)
95
+ string = object.to_s.force_encoding(Encoding::ASCII_8BIT)
96
+ "#{ object.type } #{ string.bytesize }\0#{ string }"
97
+ end
98
+
99
+ def hash_content(string)
100
+ Digest::SHA1.hexdigest(string)
101
+ end
102
+
103
+ def read_object(oid)
104
+ raw = load_raw(oid)
105
+ scanner = StringScanner.new(raw.data)
106
+
107
+ object = TYPES[raw.type].parse(scanner)
108
+ object.oid = oid
109
+
110
+ object
111
+ end
112
+ end
@@ -0,0 +1,27 @@
1
+ require "time"
2
+
3
+ class Database
4
+ TIME_FORMAT = "%s %z"
5
+
6
+ Author = Struct.new(:name, :email, :time) do
7
+ def self.parse(string)
8
+ name, email, time = string.split(/<|>/).map(&:strip)
9
+ time = Time.strptime(time, TIME_FORMAT)
10
+
11
+ Author.new(name, email, time)
12
+ end
13
+
14
+ def short_date
15
+ time.strftime("%Y-%m-%d")
16
+ end
17
+
18
+ def readable_time
19
+ time.strftime("%a %b %-d %H:%M:%S %Y %z")
20
+ end
21
+
22
+ def to_s
23
+ timestamp = time.strftime(TIME_FORMAT)
24
+ "#{ name } <#{ email }> #{ timestamp }"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ require "forwardable"
2
+
3
+ require_relative "./loose"
4
+ require_relative "./packed"
5
+
6
+ class Database
7
+ class Backends
8
+
9
+ extend Forwardable
10
+ def_delegators :@loose, :write_object
11
+
12
+ def initialize(pathname)
13
+ @pathname = pathname
14
+ @loose = Loose.new(pathname)
15
+ @stores = [@loose] + packed
16
+ end
17
+
18
+ def pack_path
19
+ @pathname.join("pack")
20
+ end
21
+
22
+ def has?(oid)
23
+ @stores.any? { |store| store.has?(oid) }
24
+ end
25
+
26
+ def load_info(oid)
27
+ @stores.reduce(nil) { |info, store| info || store.load_info(oid) }
28
+ end
29
+
30
+ def load_raw(oid)
31
+ @stores.reduce(nil) { |raw, store| raw || store.load_raw(oid) }
32
+ end
33
+
34
+ def prefix_match(name)
35
+ oids = @stores.reduce([]) do |list, store|
36
+ list + store.prefix_match(name)
37
+ end
38
+
39
+ oids.uniq
40
+ end
41
+
42
+ private
43
+
44
+ def packed
45
+ packs = Dir.entries(pack_path).grep(/\.pack$/)
46
+ .map { |name| pack_path.join(name) }
47
+ .sort_by { |path| File.mtime(path) }
48
+ .reverse
49
+
50
+ packs.map { |path| Packed.new(path) }
51
+
52
+ rescue Errno::ENOENT
53
+ []
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,24 @@
1
+ class Database
2
+ class Blob
3
+
4
+ attr_accessor :oid
5
+ attr_reader :data
6
+
7
+ def self.parse(scanner)
8
+ Blob.new(scanner.rest)
9
+ end
10
+
11
+ def initialize(data)
12
+ @data = data
13
+ end
14
+
15
+ def type
16
+ "blob"
17
+ end
18
+
19
+ def to_s
20
+ @data
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,70 @@
1
+ require_relative "./author"
2
+
3
+ class Database
4
+ class Commit
5
+
6
+ attr_accessor :oid
7
+ attr_reader :parents, :tree, :author, :committer, :message
8
+
9
+ def self.parse(scanner)
10
+ headers = Hash.new { |hash, key| hash[key] = [] }
11
+
12
+ loop do
13
+ line = scanner.scan_until(/\n/).strip
14
+ break if line == ""
15
+
16
+ key, value = line.split(/ +/, 2)
17
+ headers[key].push(value)
18
+ end
19
+
20
+ Commit.new(
21
+ headers["parent"],
22
+ headers["tree"].first,
23
+ Author.parse(headers["author"].first),
24
+ Author.parse(headers["committer"].first),
25
+ scanner.rest)
26
+ end
27
+
28
+ def initialize(parents, tree, author, committer, message)
29
+ @parents = parents
30
+ @tree = tree
31
+ @author = author
32
+ @committer = committer
33
+ @message = message
34
+ end
35
+
36
+ def merge?
37
+ @parents.size > 1
38
+ end
39
+
40
+ def parent
41
+ @parents.first
42
+ end
43
+
44
+ def date
45
+ @committer.time
46
+ end
47
+
48
+ def title_line
49
+ @message.lines.first
50
+ end
51
+
52
+ def type
53
+ "commit"
54
+ end
55
+
56
+ def to_s
57
+ lines = []
58
+
59
+ lines.push("tree #{ @tree }")
60
+ lines.concat(@parents.map { |oid| "parent #{ oid }" })
61
+ lines.push("author #{ @author }")
62
+ lines.push("committer #{ @committer }")
63
+ lines.push("")
64
+ lines.push(@message)
65
+
66
+ lines.join("\n")
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,7 @@
1
+ class Database
2
+ Entry = Struct.new(:oid, :mode) do
3
+ def tree?
4
+ mode == Tree::TREE_MODE
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,70 @@
1
+ require "strscan"
2
+ require "zlib"
3
+
4
+ require_relative "../temp_file"
5
+
6
+ class Database
7
+ class Loose
8
+
9
+ def initialize(pathname)
10
+ @pathname = pathname
11
+ end
12
+
13
+ def has?(oid)
14
+ File.file?(object_path(oid))
15
+ end
16
+
17
+ def load_info(oid)
18
+ type, size, _ = read_object_header(oid, 128)
19
+ Raw.new(type, size)
20
+ rescue Errno::ENOENT
21
+ nil
22
+ end
23
+
24
+ def load_raw(oid)
25
+ type, size, scanner = read_object_header(oid)
26
+ Raw.new(type, size, scanner.rest)
27
+ rescue Errno::ENOENT
28
+ nil
29
+ end
30
+
31
+ def prefix_match(name)
32
+ dirname = object_path(name).dirname
33
+
34
+ oids = Dir.entries(dirname).map do |filename|
35
+ "#{ dirname.basename }#{ filename }"
36
+ end
37
+
38
+ oids.select { |oid| oid.start_with?(name) }
39
+ rescue Errno::ENOENT
40
+ []
41
+ end
42
+
43
+ def write_object(oid, content)
44
+ path = object_path(oid)
45
+ return if File.exist?(path)
46
+
47
+ file = TempFile.new(path.dirname, "tmp_obj")
48
+ file.write(Zlib::Deflate.deflate(content, Zlib::BEST_SPEED))
49
+ file.move(path.basename)
50
+ end
51
+
52
+ private
53
+
54
+ def object_path(oid)
55
+ @pathname.join(oid[0..1], oid[2..-1])
56
+ end
57
+
58
+ def read_object_header(oid, read_bytes = nil)
59
+ path = object_path(oid)
60
+ data = Zlib::Inflate.new.inflate(File.read(path, read_bytes))
61
+ scanner = StringScanner.new(data)
62
+
63
+ type = scanner.scan_until(/ /).strip
64
+ size = scanner.scan_until(/\0/)[0..-2].to_i
65
+
66
+ [type, size, scanner]
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,75 @@
1
+ require "forwardable"
2
+
3
+ require_relative "../pack/expander"
4
+ require_relative "../pack/index"
5
+ require_relative "../pack/reader"
6
+
7
+ class Database
8
+ class Packed
9
+
10
+ extend Forwardable
11
+ def_delegators :@index, :prefix_match
12
+
13
+ def initialize(pathname)
14
+ @pack_file = File.open(pathname, File::RDONLY)
15
+ @reader = Pack::Reader.new(@pack_file)
16
+
17
+ @index_file = File.open(pathname.sub_ext(".idx"), File::RDONLY)
18
+ @index = Pack::Index.new(@index_file)
19
+ end
20
+
21
+ def has?(oid)
22
+ @index.oid_offset(oid) != nil
23
+ end
24
+
25
+ def load_info(oid)
26
+ offset = @index.oid_offset(oid)
27
+ offset ? load_info_at(offset) : nil
28
+ end
29
+
30
+ def load_raw(oid)
31
+ offset = @index.oid_offset(oid)
32
+ offset ? load_raw_at(offset) : nil
33
+ end
34
+
35
+ private
36
+
37
+ def load_info_at(offset)
38
+ @pack_file.seek(offset)
39
+ record = @reader.read_info
40
+
41
+ case record
42
+ when Pack::Record
43
+ Raw.new(record.type, record.data)
44
+ when Pack::OfsDelta
45
+ base = load_info_at(offset - record.base_ofs)
46
+ Raw.new(base.type, record.delta_data)
47
+ when Pack::RefDelta
48
+ base = load_info(record.base_oid)
49
+ Raw.new(base.type, record.delta_data)
50
+ end
51
+ end
52
+
53
+ def load_raw_at(offset)
54
+ @pack_file.seek(offset)
55
+ record = @reader.read_record
56
+
57
+ case record
58
+ when Pack::Record
59
+ record
60
+ when Pack::OfsDelta
61
+ base = load_raw_at(offset - record.base_ofs)
62
+ expand_delta(base, record)
63
+ when Pack::RefDelta
64
+ base = load_raw(record.base_oid)
65
+ expand_delta(base, record)
66
+ end
67
+ end
68
+
69
+ def expand_delta(base, record)
70
+ data = Pack::Expander.expand(base.data, record.delta_data)
71
+ Pack::Record.new(base.type, data)
72
+ end
73
+
74
+ end
75
+ end