blaml 1.0.0.pre → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,7 @@ README.rdoc
5
5
  Rakefile
6
6
  lib/blaml.rb
7
7
  lib/blaml/blamed_io.rb
8
+ lib/blaml/git_blamer.rb
8
9
  lib/blaml/meta.rb
9
10
  lib/blaml/to_ruby.rb
10
11
  lib/blaml/tree_builder.rb
@@ -1,11 +1,11 @@
1
1
  = Blaml
2
2
 
3
- * http://github.com/yaksnrainbows/blaml
3
+ * http://yaks.me/blaml
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
7
  Blaml is a parser based on Psych (ruby 1.9 only) for yaml files that have
8
- been blamed with git.
8
+ been blamed with a SCM.
9
9
  Blaml parses the blamed yaml file and makes the blame metadata available on the
10
10
  returned ruby object through a 'meta' attribute.
11
11
 
@@ -13,12 +13,29 @@ returned ruby object through a 'meta' attribute.
13
13
 
14
14
  * Load blamed yaml files and access blame data as metadata.
15
15
 
16
- * Currently only works on blamed files generated with 'git blame -f file.yml'
16
+ * Supports custom SCM blaming and parsing (see Blaml::GitBlamer).
17
17
 
18
- == SYNOPSIS:
18
+ == USAGE:
19
+
20
+ Using the built in GitBlamer:
19
21
 
20
22
  b = Blaml.load `git blame -f file.yml`
21
23
 
24
+ b = Blaml.blame_file "file.yml"
25
+
26
+ Using a custom SCM blamer class:
27
+
28
+ # Note: First define SvnBlamer with the same interface as GitBlamer
29
+
30
+ # Explicitely use a different blamer:
31
+ b = Blaml.blame_file "file.yml", SvnBlamer
32
+
33
+ # Always use a different blamer:
34
+ Blaml.default_blamer = SvnBlamer
35
+ b = Blaml.blame_file "file.yml"
36
+
37
+ Working with the blamed data:
38
+
22
39
  b.meta
23
40
  # => Returns metadata hash for most recent change in this data structure.
24
41
 
@@ -2,6 +2,7 @@ require 'time'
2
2
  require 'psych'
3
3
  require 'yaml'
4
4
 
5
+ require 'blaml/git_blamer'
5
6
  require 'blaml/blamed_io'
6
7
  require 'blaml/tree_builder'
7
8
  require 'blaml/meta'
@@ -10,19 +11,25 @@ require 'blaml/to_ruby'
10
11
  class Blaml
11
12
 
12
13
  # This gem's version.
13
- VERSION = "1.0.0.pre"
14
+ VERSION = "1.0.0"
15
+
16
+ class << self
17
+ # The default blamer interface to use.
18
+ attr_accessor :default_blamer
19
+ end
20
+
21
+ self.default_blamer = GitBlamer
22
+
14
23
 
15
24
  ###
16
25
  # Load +yaml+ in to a Ruby data structure. If multiple documents are
17
26
  # provided, the object contained in the first document will be returned.
18
27
  #
19
- # Example:
20
- #
21
- # Psych.load("--- a") # => 'a'
22
- # Psych.load("---\n - a\n - b") # => ['a', 'b']
28
+ # Pass an optional blamer object for blame data parsing
29
+ # (defaults to Blaml.default_blamer).
23
30
 
24
- def self.load yaml
25
- result = parse(yaml)
31
+ def self.load yaml, blamer=nil
32
+ result = parse(yaml, blamer)
26
33
  result ? result.to_blamed_ruby : result
27
34
  end
28
35
 
@@ -32,32 +39,43 @@ class Blaml
32
39
  # as a list. For example:
33
40
  #
34
41
  # Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
35
- #
36
- def self.load_stream yaml
37
- parse_stream(yaml).children.map { |child| child.to_blamed_ruby }
42
+
43
+ def self.load_stream yaml, blamer=nil
44
+ parse_stream(yaml, blamer).children.map { |child| child.to_blamed_ruby }
38
45
  end
39
46
 
40
47
 
41
48
  ###
42
- # Load the document contained in +filename+. Returns the yaml contained in
43
- # +filename+ as a ruby object
49
+ # Load the blamed document contained in +filename+.
50
+ # Returns the yaml contained in +filename+ as a ruby object
44
51
 
45
- def self.load_file filename
46
- self.load File.open(filename)
52
+ def self.load_file filename, blamer=nil
53
+ self.load File.open(filename), blamer
54
+ end
55
+
56
+
57
+ ##
58
+ # Blame the given file and load the output.
59
+ # Pass an optional blamer object for blame data parsing
60
+ # (defaults to Blaml.default_blamer).
61
+
62
+ def self.blame_file filename, blamer=nil
63
+ blamer ||= self.default_blamer
64
+ self.load blamer.blame(filename), blamer
47
65
  end
48
66
 
49
67
 
50
68
  ###
51
- # Parse a YAML string in +yaml+. Returns the first object of a YAML AST.
69
+ # Parse a blamed YAML string in +yaml+.
70
+ # Returns the first object of a YAML AST.
52
71
  #
53
- # Example:
54
- #
55
- # Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Sequence:0x00>
56
- #
57
- # See Psych::Nodes for more information about YAML AST.
72
+ # Pass an optional blamer object for blame data parsing
73
+ # (defaults to self.default_blamer).
74
+
75
+ def self.parse yaml, blamer=nil
76
+ io = BlamedIO.new yaml, blamer
58
77
 
59
- def self.parse yaml
60
- children = parse_stream(BlamedIO.new(yaml)).children
78
+ children = parse_stream(io).children
61
79
  children.empty? ? false : children.first.children.first
62
80
  end
63
81
 
@@ -65,9 +83,9 @@ class Blaml
65
83
  ###
66
84
  # Parse a file at +filename+. Returns the YAML AST.
67
85
 
68
- def self.parse_file filename
86
+ def self.parse_file filename, blamer=nil
69
87
  File.open filename do |f|
70
- parse f
88
+ parse f, blamer
71
89
  end
72
90
  end
73
91
 
@@ -85,7 +103,7 @@ class Blaml
85
103
  # Returns the full AST for the YAML document with blame metadata.
86
104
  # See Psych::parse_stream for more info.
87
105
 
88
- def self.parse_stream blaml
106
+ def self.parse_stream blaml, blamer=nil
89
107
  parser = self.parser blaml
90
108
  parser.parse blaml
91
109
  parser.handler.root
@@ -6,25 +6,21 @@ class Blaml
6
6
 
7
7
  class BlamedIO
8
8
 
9
- DATE_MATCHER =
10
- %r{(\d+[-\s:]){6}[^\s]+}
11
-
12
- META_MATCHER =
13
- %r{([^\s]+)\s+([^\s]+)\s+\(([^\s]+)\s+(#{DATE_MATCHER})\s+(\d+)\)\s}
14
-
15
9
  # Accessor for currently available metadata.
16
10
  attr_reader :metadata
17
11
 
18
-
19
12
  ##
20
13
  # Create new BlamedIO with a string or IO object.
14
+ # Pass an optional blamer object for blame data parsing
15
+ # (defaults to Blaml.default_blamer).
21
16
 
22
- def initialize io
17
+ def initialize io, blamer=nil
23
18
  io = StringIO.new io if String === io
24
19
 
25
20
  @io = io
26
21
  @metadata = []
27
22
  @meta_mode = true
23
+ @blamer = blamer || Blaml.default_blamer
28
24
  end
29
25
 
30
26
 
@@ -132,11 +128,11 @@ class Blaml
132
128
  # Reads blame metadata.
133
129
 
134
130
  def read_meta
135
- buffer = ""
136
-
131
+ buffer = ""
132
+ meta = nil
137
133
  start_pos = @io.pos
138
134
 
139
- until buffer =~ META_MATCHER do
135
+ until meta = @blamer.parse(buffer) do
140
136
 
141
137
  # Got to the end of line with no metadata.
142
138
  # Assume we're reading a regular yml IO.
@@ -149,15 +145,7 @@ class Blaml
149
145
  buffer << @io.getc
150
146
  end
151
147
 
152
- meta_key = {
153
- :file => $2,
154
- :line => $6.to_i,
155
- :author => $3,
156
- :commit => $1,
157
- :updated_at => Time.parse($4)
158
- }
159
-
160
- @metadata << [meta_key]
148
+ @metadata << [meta]
161
149
 
162
150
  true
163
151
  end
@@ -0,0 +1,52 @@
1
+ class Blaml
2
+
3
+ ##
4
+ # The interface for git repo interaction.
5
+ # Write your own for other scm tools!
6
+
7
+ class GitBlamer
8
+
9
+ DATE_MATCHER =
10
+ %r{(\d+[-\s:]){6}[^\s]+}
11
+
12
+ META_MATCHER =
13
+ %r{([^\s]+)\s+([^\s]+)\s+\(([^\s]+)\s+(#{DATE_MATCHER})\s+(\d+)\)\s}
14
+
15
+
16
+ ##
17
+ # Returns the blamed contents of the given file.
18
+
19
+ def self.blame filepath
20
+ filepath, filename = File.split filepath
21
+
22
+ blame_str = `cd #{filepath} && git blame -f #{filename}`
23
+ raise blame_str unless $?.success?
24
+
25
+ blame_str
26
+ end
27
+
28
+
29
+ ##
30
+ # Parses the given string for blame data, returns a hash with blame data
31
+ # or nil if unparsable.
32
+ #
33
+ # Hash keys returned are:
34
+ # :file:: String - The filepath
35
+ # :line:: Integer - The line this data came from
36
+ # :author:: String - The username of the author of the change
37
+ # :commit:: String - The revision identifier of the commit
38
+ # :updated_at:: Time - The time when the commit was made
39
+
40
+ def self.parse str
41
+ return unless str =~ META_MATCHER
42
+
43
+ {
44
+ :file => $2,
45
+ :line => $6.to_i,
46
+ :author => $3,
47
+ :commit => $1,
48
+ :updated_at => Time.parse($4)
49
+ }
50
+ end
51
+ end
52
+ end
@@ -63,6 +63,14 @@ class Blaml
63
63
  def to_value
64
64
  @value
65
65
  end
66
+
67
+
68
+ ##
69
+ # Output @value yaml string.
70
+
71
+ def to_yaml
72
+ self.to_value.to_yaml
73
+ end
66
74
  end
67
75
 
68
76
 
@@ -75,15 +83,18 @@ class Blaml
75
83
  # Returns the child metadata with the most recent change.
76
84
 
77
85
  def meta
78
- meta = nil
86
+ meta = nil
87
+ path_key = nil
79
88
 
80
- @value.each do |val|
89
+ @value.each_with_index do |val, i|
81
90
  next unless val.respond_to? :meta
82
91
 
83
- meta = val.meta if !meta ||
92
+ meta = val.meta.dup and path_key = i if !meta ||
84
93
  meta && val.meta && val.meta[:updated_at] > meta[:updated_at]
85
94
  end
86
95
 
96
+ (meta[:path] ||= []).unshift path_key if meta && path_key
97
+
87
98
  meta
88
99
  end
89
100
 
@@ -152,20 +163,28 @@ class Blaml
152
163
  # Returns the child metadata with the most recent change.
153
164
 
154
165
  def meta
155
- meta = nil
166
+ meta = nil
167
+ path_key = nil
156
168
 
157
169
  @value.each do |key, val|
158
170
  if val.respond_to? :meta
159
- meta = val.meta if !meta ||
171
+ if !meta ||
160
172
  meta && val.meta && val.meta[:updated_at] > meta[:updated_at]
173
+ meta = val.meta.dup
174
+ path_key = key
175
+ end
161
176
  end
162
177
 
163
178
  if key.respond_to? :meta
164
- meta = key.meta if !meta ||
179
+ if !meta ||
165
180
  meta && val.meta && key.meta[:updated_at] > meta[:updated_at]
181
+ meta = key.meta.dup
182
+ end
166
183
  end
167
184
  end
168
185
 
186
+ (meta[:path] ||= []).unshift path_key if meta && path_key
187
+
169
188
  meta
170
189
  end
171
190
 
metadata CHANGED
@@ -1,32 +1,52 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre
5
- prerelease: 6
4
+ version: 1.0.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jeremie Castagna
9
- autorequire: !!null
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-02-03 00:00:00.000000000 -08:00
13
- default_executable: !!null
12
+ date: 2012-07-18 00:00:00.000000000 Z
14
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdoc
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.10'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.10'
15
30
  - !ruby/object:Gem::Dependency
16
31
  name: hoe
17
- requirement: &2156751600 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
18
33
  none: false
19
34
  requirements:
20
- - - ! '>='
35
+ - - ~>
21
36
  - !ruby/object:Gem::Version
22
- version: 2.9.0
37
+ version: '3.0'
23
38
  type: :development
24
39
  prerelease: false
25
- version_requirements: *2156751600
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.0'
26
46
  description: ! 'Blaml is a parser based on Psych (ruby 1.9 only) for yaml files that
27
47
  have
28
48
 
29
- been blamed with git.
49
+ been blamed with a SCM.
30
50
 
31
51
  Blaml parses the blamed yaml file and makes the blame metadata available on the
32
52
 
@@ -36,8 +56,8 @@ email:
36
56
  executables: []
37
57
  extensions: []
38
58
  extra_rdoc_files:
39
- - Manifest.txt
40
59
  - History.rdoc
60
+ - Manifest.txt
41
61
  - README.rdoc
42
62
  files:
43
63
  - .autotest
@@ -47,15 +67,15 @@ files:
47
67
  - Rakefile
48
68
  - lib/blaml.rb
49
69
  - lib/blaml/blamed_io.rb
70
+ - lib/blaml/git_blamer.rb
50
71
  - lib/blaml/meta.rb
51
72
  - lib/blaml/to_ruby.rb
52
73
  - lib/blaml/tree_builder.rb
53
74
  - test/test_blaml.rb
54
75
  - .gemtest
55
- has_rdoc: true
56
- homepage: http://github.com/yaksnrainbows/blaml
76
+ homepage: http://yaks.me/blaml
57
77
  licenses: []
58
- post_install_message: !!null
78
+ post_install_message:
59
79
  rdoc_options:
60
80
  - --main
61
81
  - README.rdoc
@@ -70,15 +90,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
90
  required_rubygems_version: !ruby/object:Gem::Requirement
71
91
  none: false
72
92
  requirements:
73
- - - ! '>'
93
+ - - ! '>='
74
94
  - !ruby/object:Gem::Version
75
- version: 1.3.1
95
+ version: '0'
76
96
  requirements: []
77
97
  rubyforge_project: blaml
78
- rubygems_version: 1.5.0
79
- signing_key: !!null
98
+ rubygems_version: 1.8.23
99
+ signing_key:
80
100
  specification_version: 3
81
101
  summary: Blaml is a parser based on Psych (ruby 1.9 only) for yaml files that have
82
- been blamed with git
102
+ been blamed with a SCM
83
103
  test_files:
84
104
  - test/test_blaml.rb