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.
- data/Manifest.txt +1 -0
- data/README.rdoc +21 -4
- data/lib/blaml.rb +43 -25
- data/lib/blaml/blamed_io.rb +8 -20
- data/lib/blaml/git_blamer.rb +52 -0
- data/lib/blaml/meta.rb +25 -6
- metadata +39 -19
data/Manifest.txt
CHANGED
data/README.rdoc
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
= Blaml
|
2
2
|
|
3
|
-
* http://
|
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
|
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
|
-
*
|
16
|
+
* Supports custom SCM blaming and parsing (see Blaml::GitBlamer).
|
17
17
|
|
18
|
-
==
|
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
|
|
data/lib/blaml.rb
CHANGED
@@ -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
|
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
|
-
#
|
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+.
|
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+.
|
69
|
+
# Parse a blamed YAML string in +yaml+.
|
70
|
+
# Returns the first object of a YAML AST.
|
52
71
|
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
-
|
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
|
data/lib/blaml/blamed_io.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
data/lib/blaml/meta.rb
CHANGED
@@ -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
|
86
|
+
meta = nil
|
87
|
+
path_key = nil
|
79
88
|
|
80
|
-
@value.
|
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
|
166
|
+
meta = nil
|
167
|
+
path_key = nil
|
156
168
|
|
157
169
|
@value.each do |key, val|
|
158
170
|
if val.respond_to? :meta
|
159
|
-
|
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
|
-
|
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
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jeremie Castagna
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
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:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
18
33
|
none: false
|
19
34
|
requirements:
|
20
|
-
- -
|
35
|
+
- - ~>
|
21
36
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
37
|
+
version: '3.0'
|
23
38
|
type: :development
|
24
39
|
prerelease: false
|
25
|
-
version_requirements:
|
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
|
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
|
-
|
56
|
-
homepage: http://github.com/yaksnrainbows/blaml
|
76
|
+
homepage: http://yaks.me/blaml
|
57
77
|
licenses: []
|
58
|
-
post_install_message:
|
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:
|
95
|
+
version: '0'
|
76
96
|
requirements: []
|
77
97
|
rubyforge_project: blaml
|
78
|
-
rubygems_version: 1.
|
79
|
-
signing_key:
|
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
|
102
|
+
been blamed with a SCM
|
83
103
|
test_files:
|
84
104
|
- test/test_blaml.rb
|