v 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.document +5 -0
  2. data/.gitignore +23 -0
  3. data/.watchr +24 -0
  4. data/.yardoc +0 -0
  5. data/LICENSE +20 -0
  6. data/README.markdown +146 -0
  7. data/Rakefile +56 -0
  8. data/VERSION +1 -0
  9. data/auto_commit.rb +131 -0
  10. data/lib/v/adapters/git/branches.rb +115 -0
  11. data/lib/v/adapters/git/commits.rb +55 -0
  12. data/lib/v/adapters/git/environment.rb +99 -0
  13. data/lib/v/adapters/git/index.rb +63 -0
  14. data/lib/v/adapters/git/object.rb +104 -0
  15. data/lib/v/adapters/git/object_types/blob.rb +24 -0
  16. data/lib/v/adapters/git/object_types/commit.rb +124 -0
  17. data/lib/v/adapters/git/object_types/tag.rb +23 -0
  18. data/lib/v/adapters/git/object_types/tree.rb +51 -0
  19. data/lib/v/adapters/git/operations/add_to_index.rb +30 -0
  20. data/lib/v/adapters/git/operations/branch.rb +42 -0
  21. data/lib/v/adapters/git/operations/commit_index.rb +39 -0
  22. data/lib/v/adapters/git/operations/diff_index.rb +20 -0
  23. data/lib/v/adapters/git/operations/initialize_repository.rb +21 -0
  24. data/lib/v/adapters/git/operations/list_files.rb +38 -0
  25. data/lib/v/adapters/git/operations/list_tree.rb +30 -0
  26. data/lib/v/adapters/git/operations/push_references_to_remote.rb +25 -0
  27. data/lib/v/adapters/git/operations/remove_from_index.rb +25 -0
  28. data/lib/v/adapters/git/operations/reset_index.rb +25 -0
  29. data/lib/v/adapters/git/operations/show_log.rb +23 -0
  30. data/lib/v/adapters/git/operations/show_object.rb +21 -0
  31. data/lib/v/adapters/git/operations/tag.rb +29 -0
  32. data/lib/v/adapters/git/participation.rb +18 -0
  33. data/lib/v/adapters/git/remotes.rb +19 -0
  34. data/lib/v/adapters/git/status.rb +60 -0
  35. data/lib/v/adapters/git.rb +27 -0
  36. data/lib/v/adapters.rb +25 -0
  37. data/lib/v/arguments.rb +102 -0
  38. data/lib/v/errors.rb +39 -0
  39. data/lib/v/future.rb +46 -0
  40. data/lib/v/operation.rb +94 -0
  41. data/lib/v/worker.rb +73 -0
  42. data/lib/v.rb +29 -0
  43. data/test/teststrap.rb +4 -0
  44. data/test/v_test.rb +32 -0
  45. data/test/work_tree/file +1 -0
  46. data/v.gemspec +97 -0
  47. metadata +131 -0
@@ -0,0 +1,63 @@
1
+ module V
2
+ module Adapters
3
+ module Git
4
+ # http://book.git-scm.com/7_the_git_index.html
5
+ class Index
6
+ include V::Adapters::Git
7
+
8
+ def initialize(environment)
9
+ @environment = environment
10
+ end
11
+
12
+ def add(*files)
13
+ @environment.add *files
14
+ end
15
+ alias_method :<<, :add
16
+
17
+ def include?(filename)
18
+ @environment.ls_files(filename) !~ /^\s*$/
19
+ end
20
+
21
+ def +(other)
22
+ raise NotImplementedError, 'TODO: implement Index#+(other)'
23
+ end
24
+
25
+ def -(other)
26
+ other.is_a? Git::Object or
27
+ raise ArgumentError, 'expected Git::Object'
28
+
29
+ name = case other
30
+ when Commit
31
+ other.name
32
+ when Tree
33
+ other.name
34
+ when Tag
35
+ other.name
36
+ when Blob
37
+ raise NotImplementedError, 'TODO: implement Index#-(other)'
38
+ else raise p(other)
39
+ end
40
+
41
+ @environment.diff_index name,
42
+ :name_status => true, :cached => true do |out, err|
43
+ Status.new out
44
+ end
45
+ end
46
+
47
+ def commit(*args)
48
+ @environment.commit *args
49
+ end
50
+ def reset(*args)
51
+ @environment.reset *args
52
+ end
53
+
54
+ protected
55
+
56
+ def assign(attrs)
57
+ attrs.each { |k, v| instance_variable_set :"@#{ k }", v }
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,104 @@
1
+ module V
2
+ module Adapters
3
+ module Git
4
+ class ObjectType
5
+ include Singleton
6
+
7
+ # Returns true if other is a Git::Object and has the same type, false
8
+ # otherwise.
9
+ def ===(object)
10
+ object.is_a? Git::Object and object.type == self
11
+ end
12
+
13
+ # See ObjectType#===.
14
+ def self.===(object)
15
+ instance === object
16
+ end
17
+
18
+ def content(object)
19
+ raise NotImplementedError
20
+ end
21
+ def to_s(object = nil)
22
+ object ? object.name : self.class.name
23
+ end
24
+ end
25
+
26
+ # http://book.git-scm.com/1_the_git_object_model.html
27
+ class Object
28
+
29
+ DEFN = 'def %s(*args, &block) type.%s self, *args, &block end'
30
+ def self.register_methods(*methods)
31
+ methods.each { |method| class_eval DEFN.gsub('%s', method.to_s) }
32
+ end
33
+ @@types = {}
34
+ def self.register_type(type)
35
+ @@types.update type
36
+ end
37
+
38
+ attr_reader :name, :environment
39
+
40
+ def initialize(environment, attrs)
41
+ @environment = environment
42
+ assign attrs
43
+ end
44
+
45
+ # Keep this lazy! Most objects only need a name.
46
+ def type
47
+ @@types.fetch @type
48
+ end
49
+
50
+ # Content depends on type. Since this object is typecasted on demand
51
+ # content can be assigned during initialize (e.g. after commit).
52
+ def content(reload = false)
53
+ @content = type.content self if reload or not defined? @content
54
+ @content
55
+ end
56
+ def size
57
+ content.size
58
+ end
59
+ alias_method :length, :size
60
+
61
+ def to_s
62
+ type.to_s self
63
+ end
64
+
65
+ INSPECT_EXCLUDES = [:'@content', :'@name', :'@type']
66
+ def inspect
67
+ attrs = instance_variables.inject([]) { |m, i|
68
+ if INSPECT_EXCLUDES.include? :"#{ i }" then m
69
+ else
70
+ m << "#{ i }=#{ instance_variable_get(:"#{ i }").inspect }"
71
+ end
72
+ } * ' '
73
+ type = "#{ @type }".capitalize
74
+
75
+ "#<Git::#{ type }:#{ @name } #{ attrs } @content=[...]>"
76
+ end
77
+
78
+ # Returns the path to the object in the current root.
79
+ def path(*basenames)
80
+ type.path @parent, @basenames, *basenames
81
+ end
82
+
83
+ # Returns true if the other object has the same type and name, false
84
+ # otherwise.
85
+ def ==(other)
86
+ type === other and name == other.name
87
+ end
88
+
89
+ protected
90
+
91
+ def assign(attrs)
92
+ attrs.each { |k, v| instance_variable_set :"@#{ k }", v }
93
+ end
94
+
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ begin
101
+ __dir__ = File.dirname __FILE__
102
+ %w[ commit tree blob tag ].
103
+ each { |basename| require "#{ __dir__ }/object_types/#{ basename }" }
104
+ end
@@ -0,0 +1,24 @@
1
+ module V
2
+ module Adapters
3
+ module Git
4
+ class Blob < ObjectType
5
+
6
+ def content(object)
7
+ object.environment.show object.name, :pretty => :raw
8
+ end
9
+
10
+ def path(parent, basename)
11
+ parent.path basename
12
+ end
13
+
14
+ def [](object, *args)
15
+ object.content[*args]
16
+ end
17
+
18
+ Object.register_type :blob => instance
19
+ Object.register_methods :[]
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,124 @@
1
+ module V
2
+ module Adapters
3
+ module Git
4
+ class Commit < ObjectType
5
+
6
+ # Completes :name in <tt>attrs</tt> and returns a Git::Object with
7
+ # type :commit.
8
+ def self.with(environment, attrs = {})
9
+ if attrs[:name].length < 40
10
+ glob = File.join environment.git_dir, 'objects',
11
+ attrs[:name][0, 2], "#{ attrs[:name][2, 38] }*"
12
+
13
+ attrs[:name] = attrs[:name][0, 2] + File.basename(Dir[ glob ].first)
14
+ end
15
+
16
+ Object.new environment, attrs.update(:type => :commit)
17
+ end
18
+
19
+ # see `git help show` for details
20
+ F = {
21
+ :commit_hash => '%H',
22
+ :commit_hash_abbrev => '%h',
23
+ :tree_hash => '%T', #
24
+ :tree_hash_abbrev => '%t',
25
+ :parent_hashes => '%P', #
26
+ :parent_hashes_abbrev => '%p',
27
+ :a_name => '%an', #
28
+ :a_name_mailmap => '%aN',
29
+ :a_email => '%ae', #
30
+ :a_email_mailmap => '%aE',
31
+ :a_date => '%ad',
32
+ :a_date_rfc2822 => '%aD',
33
+ :a_date_relative => '%ar',
34
+ :a_date_unix => '%at', #
35
+ :a_date_iso8601 => '%ai',
36
+ :c_name => '%cn', #
37
+ :c_name_mailmap => '%cN',
38
+ :c_email => '%ce', #
39
+ :c_email_mailmap => '%cE',
40
+ :c_date => '%cd',
41
+ :c_date_rfc2822 => '%cD',
42
+ :c_date_relative => '%cr',
43
+ :c_date_unix => '%ct', #
44
+ :c_date_iso8601 => '%ci',
45
+ :ref_names => '%d',
46
+ :encoding => '%e',
47
+ :subject => '%s', #
48
+ :subject_sanitized => '%f',
49
+ :body => '%b', # extra
50
+ :red => '%Cred',
51
+ :green => '%Cgreen',
52
+ :blue => '%Cblue',
53
+ :reset_color => '%Creset',
54
+ :newline => '%n',
55
+ :hex => '%%x%02x'
56
+ # o %m: left, right or boundary mark
57
+ # o %C(...): color specification, as described in color.branch.* config option
58
+ }
59
+ format = []
60
+ format<< F[:tree_hash]
61
+ format<< F[:parent_hashes]
62
+ format<< F.values_at(:a_name, :a_email, :a_date_unix) * (F[:hex] % 0)
63
+ format<< F.values_at(:c_name, :c_email, :c_date_unix) * (F[:hex] % 0)
64
+ format<< F.values_at(:subject, :body) * (F[:hex] % 0)
65
+ FORMAT = format * F[:newline]
66
+
67
+ def content(object)
68
+ object.environment.show object.name, :pretty => FORMAT
69
+ end
70
+
71
+ def tree(object)
72
+ fetch object, :tree
73
+ end
74
+ def parents(object)
75
+ fetch object, :parents
76
+ end
77
+ def author(object)
78
+ fetch object, :author
79
+ end
80
+ def committer(object)
81
+ fetch object, :commiter
82
+ end
83
+ def subject(object)
84
+ fetch object, :subject
85
+ end
86
+ def body(object)
87
+ fetch object, :body
88
+ end
89
+
90
+ def path(parent, *basenames)
91
+ basenames.compact * '/'
92
+ end
93
+
94
+ protected
95
+
96
+ def fetch(object, attribute)
97
+ content = object.content.split "\n", 5
98
+ env = object.environment
99
+
100
+ case attribute
101
+ when :tree
102
+ Tree.with env, :name => content[0], :parent => object
103
+ when :parents
104
+ content[1].split(' ').
105
+ inject({}) { |mem, name| mem.update name => Commit.with(env, :name => name) }
106
+ when :author
107
+ Participation.new :author, *content[2].split("\0")
108
+ when :commiter
109
+ Participation.new :committer, *content[3].split("\0")
110
+ when :subject
111
+ content[4].split("\0").first
112
+ when :body
113
+ content[4].split("\0").last
114
+ end
115
+ end
116
+
117
+ Object.register_type :commit => instance
118
+ Object.register_methods :tree, :parents, :author, :committer,
119
+ :subject, :body
120
+
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,23 @@
1
+ module V
2
+ module Adapters
3
+ module Git
4
+ class Tag < ObjectType
5
+
6
+ # Returns the name of the commit the object points to.
7
+ def content(obj)
8
+ path = File.join obj.environment.git_dir, %w[ refs tags ], obj.name
9
+ File.read(path).chomp
10
+ end
11
+
12
+ # Returns the commit the object points to.
13
+ def commit(object)
14
+ Commit.with object.environment, :name => object.content
15
+ end
16
+
17
+ Object.register_type :tag => instance
18
+ Object.register_methods :commit
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ module V
2
+ module Adapters
3
+ module Git
4
+ class Tree < ObjectType
5
+ include Enumerable
6
+
7
+ def self.with(environment, attrs = {})
8
+ Object.new environment, attrs.update(:type => :tree)
9
+ end
10
+
11
+ LINE_RE = /^(\d{6}) (blob|tree) ([[:alnum:]]{40})\t(.+)$/
12
+ def content(object)
13
+ environment, name, parent = object.environment, object.name, object
14
+
15
+ environment.ls_tree(name).split($/).
16
+ inject({}) do |mem, line|
17
+ mode, type, name, basename = LINE_RE.match(line).captures
18
+
19
+ # see git help ls-tree
20
+ # path.gsub! /(\\n|\\t|\\)/, ...
21
+
22
+ child = Object.new environment,
23
+ :type => type.to_sym, :name => name,
24
+ :parent => parent, :basename => basename
25
+
26
+ mem.update basename => child
27
+ end
28
+ end
29
+ def each(object)
30
+ object.content.values.each { |v| yield v }
31
+ end
32
+
33
+ def [](object, glob)
34
+ raise NotImplementedError
35
+ end
36
+ def /(object, path)
37
+ parts = path.to_s.split '/'
38
+ parts.inject(object) { |obj, name| obj.content.fetch name }
39
+ end
40
+
41
+ def path(parent, *basenames)
42
+ parent.path *basenames
43
+ end
44
+
45
+ Object.register_type :tree => instance
46
+ Object.register_methods :each, :/, :[]
47
+
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,30 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ AddToIndex = operation(:add) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ args.dry_run.n
7
+ args.verbose.v
8
+ args.force.f
9
+ args.interactive.i
10
+ args.patch.p
11
+ args.edit.e
12
+ args.all.A
13
+ args.update.u
14
+ args.intent_to_add.N
15
+ args.refresh
16
+ args.ignore_errors
17
+ args << '--'
18
+ end
19
+
20
+ include WorkTreeRequirement
21
+ def run(environment)
22
+ out, err = exec environment
23
+ err.empty? or raise V::ERROR, err
24
+
25
+ Index.new environment
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ Branch = operation(:branch) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ args.color
7
+ args.no_color
8
+ args.remote(:alias => true).r
9
+ args.all(:alias => true).a
10
+ args.verbose.v
11
+ args.abbrev(7)
12
+ args.no_abbrev
13
+ args.merged
14
+ args.no_merged
15
+ args.contains
16
+ # <commit>
17
+ args.track
18
+ args.no_track
19
+ args.reflog(:alias => true).l
20
+ args.force(:alias => true).f
21
+ # <branchname>
22
+ # <startpoint>
23
+ args.move(:alias => true).m
24
+ args.move!(:alias => true).M
25
+ # <oldbranch>
26
+ # <newbranch>
27
+ args.delete(:alias => true).d
28
+ args.delete!(:alias => true).D
29
+ # <branchname>
30
+ end
31
+
32
+ include WorkTreeRequirement
33
+ def run(environment)
34
+ out, err = exec environment
35
+ err.empty? or raise V::ERROR, err
36
+
37
+ out
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,39 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ CommitIndex = operation(:commit) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ args.all.a
7
+ args.interactive
8
+ args.signoff.s
9
+ args.verbose.v
10
+ args.untracked_files(:all).u
11
+ args.amend
12
+ args.reedit_message(nil).c
13
+ args.reuse_message(nil).C
14
+ args.file(nil).F
15
+ args.message(nil, :first => true).m
16
+ args.allow_empty
17
+ args.no_verify.n
18
+ args.edit.e
19
+ args.author nil
20
+ args.cleanup :default
21
+ args << '--'
22
+ args.include.i
23
+ args.only.o
24
+ end
25
+
26
+ include WorkTreeRequirement
27
+ def run(environment)
28
+ out, err = exec environment
29
+ err.empty? or raise V::ERROR, err
30
+
31
+ name = /^\[(?:.*) (\S+)\]/.match(out).captures.first
32
+ Commit.with environment, :name => name
33
+ rescue
34
+ return out
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ DiffIndex = operation(:diff_index) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ # TODO: complete arguments ...
7
+ args.cached
8
+ args.name_status
9
+ end
10
+
11
+ def run(environment)
12
+ out, err = exec environment
13
+ err.empty? or raise V::ERROR, err
14
+
15
+ out
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ InitializeRepository = operation(:init) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ args.quiet.q
7
+ args.bare
8
+ args.template(nil)
9
+ args.shared(:umask, false)
10
+ end
11
+
12
+ def run(environment)
13
+ out, err = exec environment
14
+ err.empty? or raise V::ERROR, err
15
+
16
+ environment
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ ListFiles = operation(:ls_files) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ args.zero(:alias => true).z
7
+ args.tags(:alias => true).t
8
+ # TODO: understand v option
9
+ args.vulgar(:alias => true).v
10
+ args.cached.c
11
+ args.deleted.d
12
+ args.others.o
13
+ args.ignored.i
14
+ args.stage.s
15
+ args.unmerge.u
16
+ args.killed.k
17
+ args.modified.m
18
+ args.exclude(nil).x
19
+ args.exclude_from(nil).X
20
+ args.exclude_per_directory(nil)
21
+ args.exclude_standard
22
+ args.error_unmatch
23
+ args.with_tree(nil)
24
+ args.full_name
25
+ args.abbrev(40)
26
+ args << '--'
27
+ end
28
+
29
+ def run(environment)
30
+ out, err = exec environment
31
+ err.empty? or raise V::ERROR, err
32
+
33
+ out
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ ListTree = operation(:ls_tree) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ # TODO: check naming
7
+ args.directories(:alias => true).d
8
+ args.recursive(:alias => true).r
9
+ # TODO: check naming
10
+ args.trace(:alias => true).t
11
+ args.long.l
12
+ args.zero(:alias => true).z
13
+ args.name_only
14
+ # TODO: implement support for non abbrev aliases
15
+ args.name_status
16
+ args.abbrev(40)
17
+ args.full_name
18
+ args.full_tree
19
+ end
20
+
21
+ def run(environment)
22
+ out, err = exec environment
23
+ err.empty? or raise V::ERROR, err
24
+
25
+ out
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ PushReferencesToRemote = operation(:push) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ args.all
7
+ args.mirror
8
+ args.tags
9
+ args.dry_run
10
+ args.porcelain
11
+ args.receive_pack nil
12
+ args.repository nil
13
+ args.thin
14
+ args.no_thin
15
+ args.force.f
16
+ args.verbose.v
17
+ end
18
+
19
+ def run(environment)
20
+ exec environment
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ RemoveFromIndex = operation(:rm) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ args.force.f
7
+ args.dry_run.n
8
+ args.recursive(:alias => true).r
9
+ args.cached
10
+ args.ignore_unmatch
11
+ args.quiet.q
12
+ args << '--'
13
+ end
14
+
15
+ include WorkTreeRequirement
16
+ def run(environment)
17
+ out, err = exec environment
18
+ err.empty? or raise V::ERROR, err
19
+
20
+ Index.new environment
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module V::Adapters::Git
2
+ module Operations
3
+ ResetIndex = operation(:reset) do
4
+ # 1.6.3.2
5
+ arguments do |args|
6
+ args.mixed
7
+ args.soft
8
+ args.hard
9
+ args.merged
10
+ args.quiet(:alias => true).q
11
+ args.commit(:HEAD, :rude => true).c
12
+ args << '--'
13
+ end
14
+
15
+ include WorkTreeRequirement
16
+ def run(environment)
17
+ out, err = exec environment
18
+ err.empty? or raise V::ERROR, err
19
+
20
+ Index.new environment
21
+ end
22
+
23
+ end
24
+ end
25
+ end