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.
- 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
|