blaml 1.0.0.pre → 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.
@@ -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