jit 0.0.0 → 1.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.
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