history 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.ruby CHANGED
@@ -54,14 +54,13 @@ title: History
54
54
  created: '2010-02-19'
55
55
  organization: Rubyworks
56
56
  summary: HISTORY and CHANGELOG parser
57
- version: 0.1.0
58
- description: ! 'History is a HISTORY and CHANGELOG file parser. It can parse common
59
- layouts for these
57
+ version: 0.2.0
58
+ description: ! 'History is a HISTORY file parser. It can parse common HISTORY file
59
+ layouts
60
60
 
61
- file types and provide their contents in a structured model. This can be useful
62
- for
61
+ and provide the contents in a structured model. This can be useful for
63
62
 
64
- a number of things, in particular it can be used to generate tag messages and add
63
+ a number of things, in particular it can be used to generate tag messages
65
64
 
66
- pre-release changelogs to relase announcements.'
67
- date: '2012-05-24'
65
+ and add pre-release change lists to release announcements.'
66
+ date: '2012-05-25'
data/DEMO.md ADDED
@@ -0,0 +1,113 @@
1
+ # History Gem
2
+
3
+ History is a HISTORY file parser. It can parse common HISTORY file layouts
4
+ and provide the contents in a structured model. This can be useful for
5
+ a number of things, in particular it can be used to generate tag messages
6
+ and add pre-release change lists to release announcements.
7
+
8
+ # History Class
9
+
10
+ The history class encapsulates this list of release
11
+ made by a project. It parses a text file by the
12
+ name of HISTORY into it indivdual relase entries.
13
+
14
+ Given a HISTORY project file containing:
15
+
16
+ = RELEASE HISTORY
17
+
18
+ == 1.2.0 / 2010-10-18
19
+
20
+ Some Dandy description of the 1.2.0 release.
21
+ This is multiline description.
22
+
23
+ Changes:
24
+
25
+ * This is change 1.
26
+ * This is change 2.
27
+ * This is change 3.
28
+
29
+
30
+ == 1.1.0 | 2010-06-06 | "Happy Days"
31
+
32
+ Some Dandy description of the 1.1.0 release.
33
+ This is multiline description. Notice the
34
+ header varies from the first.
35
+
36
+ The description can even have multiple paragraphs.
37
+
38
+ Changes:
39
+
40
+ * This is change 1.
41
+ * This is change 2.
42
+ * This is change 3.
43
+
44
+
45
+ == 1.0.0 / 2010-04-30
46
+
47
+ Some Dandy description of the 1.0.0 release.
48
+ This is multiline description. Notice that
49
+ the "changes:" label isn't strictly needed.
50
+
51
+ * This is change 1.
52
+ * This is change 2.
53
+ * This is change 3.
54
+
55
+
56
+ == 0.9.0 / 2010-04-10
57
+
58
+ 1. This is change 1.
59
+ 2. This is change 2.
60
+ 3. This is change 3.
61
+
62
+ Some Dandy description of the 0.9.0 release.
63
+ Notice this time that the changes are listed
64
+ first and are numerically enumerated.
65
+
66
+ The History class provides an interface to this information.
67
+ The initializer takes the root directory for the project
68
+ and looks for a file called +HISTORY+, optionally ending
69
+ in an extension such as +.txt+ or +.rdoc+, etc.
70
+
71
+ history = History.find('tmp/example')
72
+
73
+ Now we should have an enumeration of each release entry in
74
+ the HISTORY file.
75
+
76
+ history.releases.size.assert == 4
77
+
78
+ The non-plurual #release method will give us the first entry.
79
+ And we can see that it has been parsed into its component
80
+ attributes.
81
+
82
+ history.release.header.assert == '== 1.2.0 / 2010-10-18'
83
+ history.release.notes.assert.index('description of the 1.2.0')
84
+
85
+ The header is further parsed into version, date and nickname if given.
86
+
87
+ history.release.version.assert == '1.2.0'
88
+ history.release.date.assert == '2010-10-18'
89
+
90
+ We should see like results for the other release entries.
91
+
92
+ history.releases[2].version.assert == '1.0.0'
93
+ history.releases[2].date.assert == '2010-04-30'
94
+
95
+ history.releases[2].header.assert == '== 1.0.0 / 2010-04-30'
96
+ history.releases[2].notes.assert.index('description of the 1.0.0')
97
+ history.releases[2].changes.assert.index('This is change 1')
98
+
99
+ Even though there are variations in the formats of each entry they are
100
+ still parsed correctly. For example the second release has a nick name.
101
+
102
+ history.releases[1].nickname.assert == 'Happy Days'
103
+
104
+ And the last entry has it's changes listed before the description.
105
+
106
+ history.releases[3].header.assert == '== 0.9.0 / 2010-04-10'
107
+ history.releases[3].notes.assert.index('description of the 0.9.0')
108
+ history.releases[3].changes.assert.index('This is change 1')
109
+
110
+ The history parser is farily simplistic, but it is flexibile enough
111
+ to parse the most common HISTORY file formats.
112
+
113
+
data/HISTORY.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # RELEASE HISTORY
2
2
 
3
+ ## 0.2.0 / 2012-05-25
4
+
5
+ This the first usable release. There's actual code now ;)
6
+
7
+ Changes:
8
+
9
+ * Port code from POM project for initial implementation.
10
+ * Place variant from VCLog project in work directory for reference.
11
+
12
+
3
13
  ## 0.1.0 / 2012-05-24
4
14
 
5
15
  This is a place holder release until the first working addition
data/README.md CHANGED
@@ -9,10 +9,10 @@
9
9
 
10
10
  ## Description
11
11
 
12
- History is a HISTORY and CHANGELOG file parser. It can parse common layouts for these
13
- file types and provide their contents in a structured model. This can be useful for
14
- a number of things, in particular it can be used to generate tag messages and add
15
- pre-release changelogs to relase announcements.
12
+ History is a HISTORY file parser. It can parse common HISTORY file layouts
13
+ and provide the contents in a structured model. This can be useful for
14
+ a number of things, in particular it can be used to generate tag messages
15
+ and add pre-release change lists to release announcements.
16
16
 
17
17
 
18
18
  ## Copyrights
data/demo/00_intro.md ADDED
@@ -0,0 +1,6 @@
1
+ # History Gem
2
+
3
+ History is a HISTORY file parser. It can parse common HISTORY file layouts
4
+ and provide the contents in a structured model. This can be useful for
5
+ a number of things, in particular it can be used to generate tag messages
6
+ and add pre-release change lists to release announcements.
@@ -0,0 +1,105 @@
1
+ # History Class
2
+
3
+ The history class encapsulates this list of release
4
+ made by a project. It parses a text file by the
5
+ name of HISTORY into it indivdual relase entries.
6
+
7
+ Given a HISTORY project file containing:
8
+
9
+ = RELEASE HISTORY
10
+
11
+ == 1.2.0 / 2010-10-18
12
+
13
+ Some Dandy description of the 1.2.0 release.
14
+ This is multiline description.
15
+
16
+ Changes:
17
+
18
+ * This is change 1.
19
+ * This is change 2.
20
+ * This is change 3.
21
+
22
+
23
+ == 1.1.0 | 2010-06-06 | "Happy Days"
24
+
25
+ Some Dandy description of the 1.1.0 release.
26
+ This is multiline description. Notice the
27
+ header varies from the first.
28
+
29
+ The description can even have multiple paragraphs.
30
+
31
+ Changes:
32
+
33
+ * This is change 1.
34
+ * This is change 2.
35
+ * This is change 3.
36
+
37
+
38
+ == 1.0.0 / 2010-04-30
39
+
40
+ Some Dandy description of the 1.0.0 release.
41
+ This is multiline description. Notice that
42
+ the "changes:" label isn't strictly needed.
43
+
44
+ * This is change 1.
45
+ * This is change 2.
46
+ * This is change 3.
47
+
48
+
49
+ == 0.9.0 / 2010-04-10
50
+
51
+ 1. This is change 1.
52
+ 2. This is change 2.
53
+ 3. This is change 3.
54
+
55
+ Some Dandy description of the 0.9.0 release.
56
+ Notice this time that the changes are listed
57
+ first and are numerically enumerated.
58
+
59
+ The History class provides an interface to this information.
60
+ The initializer takes the root directory for the project
61
+ and looks for a file called +HISTORY+, optionally ending
62
+ in an extension such as +.txt+ or +.rdoc+, etc.
63
+
64
+ history = History.find('tmp/example')
65
+
66
+ Now we should have an enumeration of each release entry in
67
+ the HISTORY file.
68
+
69
+ history.releases.size.assert == 4
70
+
71
+ The non-plurual #release method will give us the first entry.
72
+ And we can see that it has been parsed into its component
73
+ attributes.
74
+
75
+ history.release.header.assert == '== 1.2.0 / 2010-10-18'
76
+ history.release.notes.assert.index('description of the 1.2.0')
77
+
78
+ The header is further parsed into version, date and nickname if given.
79
+
80
+ history.release.version.assert == '1.2.0'
81
+ history.release.date.assert == '2010-10-18'
82
+
83
+ We should see like results for the other release entries.
84
+
85
+ history.releases[2].version.assert == '1.0.0'
86
+ history.releases[2].date.assert == '2010-04-30'
87
+
88
+ history.releases[2].header.assert == '== 1.0.0 / 2010-04-30'
89
+ history.releases[2].notes.assert.index('description of the 1.0.0')
90
+ history.releases[2].changes.assert.index('This is change 1')
91
+
92
+ Even though there are variations in the formats of each entry they are
93
+ still parsed correctly. For example the second release has a nick name.
94
+
95
+ history.releases[1].nickname.assert == 'Happy Days'
96
+
97
+ And the last entry has it's changes listed before the description.
98
+
99
+ history.releases[3].header.assert == '== 0.9.0 / 2010-04-10'
100
+ history.releases[3].notes.assert.index('description of the 0.9.0')
101
+ history.releases[3].changes.assert.index('This is change 1')
102
+
103
+ The history parser is farily simplistic, but it is flexibile enough
104
+ to parse the most common HISTORY file formats.
105
+
@@ -0,0 +1,2 @@
1
+ require 'ae'
2
+ require 'ae/should'
@@ -0,0 +1,25 @@
1
+ require 'fileutils'
2
+
3
+ FIXTURE_DIR = 'tmp/example/'
4
+
5
+ # Remove the example project if it exists.
6
+ Before :all do
7
+ FileUtils.rm_r(FIXTURE_DIR) if File.exist?(FIXTURE_DIR)
8
+ File.open(FIXTURE_DIR + '/.ruby', 'w'){ |f| f << "" }
9
+ end
10
+
11
+ When 'Given an empty project directory' do
12
+ FileUtils.rm_r(FIXTURE_DIR) if File.exist?(FIXTURE_DIR)
13
+ end
14
+
15
+ When 'iven a ((([\.\w]+))) project file' do |name, text|
16
+ FileUtils.mkdir_p(FIXTURE_DIR)
17
+ File.open(FIXTURE_DIR + name, 'w') do |f|
18
+ f << text
19
+ end
20
+ end
21
+
22
+ When 'no ((([\.\w]+))) file in a project' do |name|
23
+ FileUtils.rm(FIXTURE_DIR + name)
24
+ end
25
+
@@ -0,0 +1 @@
1
+ require 'history'
data/lib/history.rb CHANGED
@@ -1 +1,124 @@
1
- # TODO
1
+ #require 'history/core_ext'
2
+ require 'history/release'
3
+
4
+ # The History class is a HISTORY file parser. It parses HISTORY files
5
+ # into a structure of individual release sections.
6
+ #
7
+ # The file is expected to be in RDoc or simple Markdown format with
8
+ # each section beginning with a secondary header (`==` or `##`) giving
9
+ # *version* and *date* of release, then a *note* followed by a point by
10
+ # point outline of *changes*.
11
+ #
12
+ # For example:
13
+ #
14
+ # == 1.0.0 / 2009-10-07
15
+ #
16
+ # Say something about this version.
17
+ #
18
+ # Changes:
19
+ #
20
+ # * outline oimportant changelog items
21
+ #
22
+ # `Changes:` is used as a parsing marker. While optional, it helps the
23
+ # parser find the list of changes, rather than looking for an asterisk
24
+ # or digit, so that ordered and unordered lists can be used in the note
25
+ # section too.
26
+ #
27
+ # Ideally, this class will be continuely imporved to handle greater
28
+ # variety of layout.
29
+ #
30
+ class History
31
+
32
+ # File glob for finding the HISTORY file.
33
+ DEFAULT_FILE = '{History}{,.*}'
34
+
35
+ # Match against version number string.
36
+ HEADER_RE = /^[=#]+\s*\d+\.\S+/
37
+
38
+ # Convenience constant for `File::FNM_CASEFOLD`.
39
+ CASEFOLD = File::FNM_CASEFOLD
40
+
41
+ #
42
+ def self.parse(text, opts={})
43
+ opts[:text] = text
44
+ new(opts[:file], opts)
45
+ end
46
+
47
+ def self.text(text, opts={})
48
+ parse(text, opts)
49
+ end
50
+
51
+ #
52
+ def self.file(file)
53
+ new(file)
54
+ end
55
+
56
+ #
57
+ def self.find(root=Dir.pwd)
58
+ file = Dir.glob(File.join(root, DEFAULT_FILE), CASEFOLD).first
59
+ new(file)
60
+ end
61
+
62
+ # HISTORY file's path.
63
+ attr :file
64
+
65
+ # HISTORY file's raw contents.
66
+ attr :text
67
+
68
+ # List of release entries.
69
+ attr :releases
70
+
71
+ # New History.
72
+ def initialize(file=nil, opts={})
73
+ if Hash === file
74
+ opts = file
75
+ file = nil
76
+ end
77
+
78
+ @file = file
79
+ @text = opts[:text]
80
+
81
+ if @file
82
+ # if file is given but no text, raise error if file not found
83
+ raise "file not found" unless File.exist?(@file) unless @text
84
+ else
85
+ @file = Dir.glob(DEFAULT_FILE, CASEFOLD).first || 'HISTORY'
86
+ end
87
+
88
+ unless @text
89
+ @text = File.read(@file) if File.exist?(@file)
90
+ end
91
+
92
+ parse
93
+ end
94
+
95
+ # Read and parse the Histoy file.
96
+ def parse
97
+ @releases = []
98
+ entry = nil
99
+
100
+ if text
101
+ text.each_line do |line|
102
+ if HEADER_RE =~ line
103
+ @releases << Release.new(entry) if entry
104
+ entry = line
105
+ else
106
+ next unless entry
107
+ entry << line
108
+ end
109
+ end
110
+ @releases << Release.new(entry)
111
+ end
112
+ end
113
+
114
+ # Lookup release by version.
115
+ def [](version)
116
+ releases.find{ |r| r.version == version }
117
+ end
118
+
119
+ # Returns first entry in releases list.
120
+ def release
121
+ releases.first
122
+ end
123
+
124
+ end #class History
data/lib/history.yml ADDED
@@ -0,0 +1,66 @@
1
+ ---
2
+ source:
3
+ - var
4
+ authors:
5
+ - name: trans
6
+ email: transfire@gmail.com
7
+ copyrights:
8
+ - holder: Rubyworks
9
+ year: '2012'
10
+ license: BSD-2-Clause
11
+ requirements:
12
+ - name: detroit
13
+ groups:
14
+ - build
15
+ development: true
16
+ - name: qed
17
+ groups:
18
+ - test
19
+ development: true
20
+ - name: ae
21
+ groups:
22
+ - test
23
+ development: true
24
+ dependencies: []
25
+ alternatives: []
26
+ conflicts: []
27
+ repositories:
28
+ - uri: git://github.com/rubyworks/history.git
29
+ scm: git
30
+ name: upstream
31
+ resources:
32
+ - uri: http://rubyworks.github.com/history
33
+ label: Website
34
+ type: home
35
+ - uri: http://github.com/rubyworks/history
36
+ label: Source Code
37
+ type: code
38
+ - uri: http://github.com/rubyworks/history/issues
39
+ label: Issue Tracker
40
+ type: bugs
41
+ - uri: http://groups.google.com/groups/rubyworks-mailinglist
42
+ label: Mailing List
43
+ type: mail
44
+ - uri: irc://us.chat.freenode.net/rubyworks
45
+ label: IRC Channel
46
+ type: chat
47
+ categories: []
48
+ extra: {}
49
+ load_path:
50
+ - lib
51
+ revision: 0
52
+ name: history
53
+ title: History
54
+ created: '2010-02-19'
55
+ organization: Rubyworks
56
+ summary: HISTORY and CHANGELOG parser
57
+ version: 0.2.0
58
+ description: ! 'History is a HISTORY file parser. It can parse common HISTORY file
59
+ layouts
60
+
61
+ and provide the contents in a structured model. This can be useful for
62
+
63
+ a number of things, in particular it can be used to generate tag messages
64
+
65
+ and add pre-release change lists to release announcements.'
66
+ date: '2012-05-25'
@@ -0,0 +1,91 @@
1
+ class History
2
+
3
+ # History release entry.
4
+ #
5
+ class Release
6
+
7
+ # The full text of the release note.
8
+ attr :text
9
+
10
+ # The header.
11
+ attr :header
12
+
13
+ # The description.
14
+ attr :notes
15
+
16
+ # The list of changes.
17
+ attr :changes
18
+
19
+ # Version number (as a string).
20
+ attr :version
21
+
22
+ # Release date.
23
+ attr :date
24
+
25
+ # Nick name of the release, if any.
26
+ attr :nickname
27
+
28
+ #
29
+ def initialize(text)
30
+ @text = text.strip
31
+ parse
32
+ end
33
+
34
+ # Returns the complete text.
35
+ def to_s
36
+ text
37
+ end
38
+
39
+ ;; private
40
+
41
+ # Parse the release text into +header+, +notes+
42
+ # and +changes+ components.
43
+ def parse
44
+ lines = text.lines.to_a
45
+
46
+ @header = lines.shift.strip
47
+
48
+ parse_release_stamp(@header)
49
+
50
+ # remove blank lines from top
51
+ lines.shift until lines.first !~ /^\s+$/
52
+
53
+ # find line that looks like the startt of a list of c hanges.
54
+ idx = nil
55
+ idx ||= lines.index{ |line| /^changes\:\s*$/i =~ line }
56
+ idx ||= lines.index{ |line| /^1.\ / =~ line }
57
+ idx ||= lines.index{ |line| /^\*\ / =~ line }
58
+
59
+ if idx.nil?
60
+ @notes = lines.join
61
+ @changes = ''
62
+ elsif idx > 0
63
+ @notes = lines[0...idx].join
64
+ @changes = lines[idx..-1].join
65
+ else
66
+ gap = lines.index{ |line| /^\s*$/ =~ line }
67
+ @changes = lines[0...gap].join
68
+ @notes = lines[gap..-1].join
69
+ end
70
+ end
71
+
72
+ # Parse out the different components of the header, such
73
+ # as `version`, release `date` and release `nick name`.
74
+ def parse_release_stamp(text)
75
+ # version
76
+ if md = /\b(\d+\.\d.*?)(\s|$)/.match(text)
77
+ @version = md[1]
78
+ end
79
+ # date
80
+ if md = /\b(\d+\-\d+\-.*?\d)(\s|\W|$)/.match(text)
81
+ @date = md[1]
82
+ end
83
+ # nickname
84
+ if md = /\"(.*?)\"/.match(text)
85
+ @nickname = md[1]
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: history
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-24 00:00:00.000000000 Z
12
+ date: 2012-05-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: detroit
16
- requirement: &23265980 !ruby/object:Gem::Requirement
16
+ requirement: &16961460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *23265980
24
+ version_requirements: *16961460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: qed
27
- requirement: &23264740 !ruby/object:Gem::Requirement
27
+ requirement: &16983160 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *23264740
35
+ version_requirements: *16983160
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: ae
38
- requirement: &23263820 !ruby/object:Gem::Requirement
38
+ requirement: &16979640 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,16 +43,15 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *23263820
47
- description: ! 'History is a HISTORY and CHANGELOG file parser. It can parse common
48
- layouts for these
46
+ version_requirements: *16979640
47
+ description: ! 'History is a HISTORY file parser. It can parse common HISTORY file
48
+ layouts
49
49
 
50
- file types and provide their contents in a structured model. This can be useful
51
- for
50
+ and provide the contents in a structured model. This can be useful for
52
51
 
53
- a number of things, in particular it can be used to generate tag messages and add
52
+ a number of things, in particular it can be used to generate tag messages
54
53
 
55
- pre-release changelogs to relase announcements.'
54
+ and add pre-release change lists to release announcements.'
56
55
  email:
57
56
  - transfire@gmail.com
58
57
  executables: []
@@ -61,12 +60,21 @@ extra_rdoc_files:
61
60
  - LICENSE.txt
62
61
  - HISTORY.md
63
62
  - README.md
63
+ - DEMO.md
64
64
  files:
65
65
  - .ruby
66
+ - demo/00_intro.md
67
+ - demo/01_history.md
68
+ - demo/applique/ae.rb
69
+ - demo/applique/fixtures.rb
70
+ - demo/applique/history.rb
71
+ - lib/history/release.rb
66
72
  - lib/history.rb
73
+ - lib/history.yml
67
74
  - LICENSE.txt
68
75
  - HISTORY.md
69
76
  - README.md
77
+ - DEMO.md
70
78
  homepage: http://rubyworks.github.com/history
71
79
  licenses:
72
80
  - BSD-2-Clause