inkan 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/LICENCE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Pat Allan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,54 @@
1
+ h1. inkan
2
+
3
+ Inspired by coming features for "Ben Hoskings'":http://benhoskin.gs/ "Babushka":http://babushka.me/, *inkan* is a library for writing out (generated) files and then checking whether they've had (manual) changes made to them.
4
+
5
+ This is particularly useful for generating configuration files and then wanting to check whether people have edited it before overwriting, but you may find other uses for it.
6
+
7
+ All it actually does is generate a SHA hash of the file's contents, and adds it as a comment at the top of the file. If the file's contents are changed, the SHA won't match, and then you can decide whether you want to overwrite the file.
8
+
9
+ h2. Installing
10
+
11
+ <pre><code>gem install inkan</code></pre>
12
+
13
+ h2. Usage
14
+
15
+ h3. Reading
16
+
17
+ To write the files
18
+
19
+ <pre><code>inkan = Inkan.new('path/to/file.txt')
20
+ inkan.print 'foo'
21
+ inkan.seal</code></pre>
22
+
23
+ Or:
24
+
25
+ <pre><code>Inkan.seal('destination') { |inkan|
26
+ inkan.print 'foo'
27
+ }</code></pre>
28
+
29
+ h3. Writing
30
+
31
+ <pre><code>Inkan.legitimate?('/path/to/file.txt')</code></pre>
32
+
33
+ h3. Customising
34
+
35
+ You can customise the header comment using the following settings:
36
+
37
+ <pre><code>inkan = Inkan.new('/path/to/file.txt')
38
+ inkan.comment = '/*' # Default is '#'.
39
+ inkan.comment_suffix = '*/' # Default is ''.
40
+ inkan.credit = 'My Magic Code' # Default is 'Generated by Inkan'</code></pre>
41
+
42
+ h2. Note on Patches/Pull Requests
43
+
44
+ The process is (ideally):
45
+
46
+ * Fork the project.
47
+ * Make your feature addition or bug fix.
48
+ * Add tests for it. This is important so things don't break in future versions.
49
+ * When committing, please don't mess with Rakefile or VERSION file. Unless, of course, you want your own version, but it'd be nice if you keep custom changes in a branch to be easily merged in.
50
+ * Send a pull request. Bonus points for topic branches.
51
+
52
+ h2. Copyright
53
+
54
+ Copyright (c) 2010 Pat Allan, released under an MIT licence.
@@ -0,0 +1,60 @@
1
+ require 'digest/sha1'
2
+
3
+ class Inkan
4
+ attr_accessor :credit, :comment, :comment_suffix
5
+
6
+ def self.legitimate?(file)
7
+ legit = false
8
+
9
+ File.open(file) do |file|
10
+ first_line = file.gets
11
+ legit = !first_line[/\s#{sha(file.read)}\s*\n$/].nil?
12
+ end
13
+
14
+ legit
15
+ end
16
+
17
+ def self.seal(file)
18
+ inkan = new(file)
19
+ yield inkan
20
+ inkan.seal
21
+ end
22
+
23
+ def self.sha(content)
24
+ Digest::SHA1.hexdigest(content)
25
+ end
26
+
27
+ def initialize(file)
28
+ @file = file
29
+
30
+ # Set Defaults
31
+ @credit = 'Generated by Inkan'
32
+ @comment = '#'
33
+ @comment_suffix = ''
34
+ end
35
+
36
+ def print(string)
37
+ file_content << string
38
+ end
39
+
40
+ def puts(string)
41
+ file_content << string << "\n"
42
+ end
43
+
44
+ def seal
45
+ File.open(@file, 'w') do |f|
46
+ f.puts "#{comment} #{credit}. #{sha} #{comment_suffix}"
47
+ f.print file_content
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def sha
54
+ self.class.sha(file_content)
55
+ end
56
+
57
+ def file_content
58
+ @file_content ||= ''
59
+ end
60
+ end
@@ -0,0 +1,131 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Inkan" do
4
+ describe '.legitimate?' do
5
+ let(:content) { 'foo bar baz' }
6
+
7
+ it "returns true if the file contents match the SHA" do
8
+ open('/tmp/spec.txt', 'w') do |file|
9
+ file.puts "# Generated by Inkan: #{Digest::SHA1.hexdigest(content)}"
10
+ file.print content
11
+ end
12
+
13
+ Inkan.legitimate?('/tmp/spec.txt').should be_true
14
+ end
15
+
16
+ it "returns false if the file contents don't match the SHA" do
17
+ open('/tmp/spec.txt', 'w') do |file|
18
+ file.puts "# Generated by Inkan: #{Digest::SHA1.hexdigest(content)}"
19
+ file.puts content
20
+ end
21
+
22
+ Inkan.legitimate?('/tmp/spec.txt').should be_false
23
+ end
24
+
25
+ it "returns false if there is no SHA" do
26
+ open('/tmp/spec.txt', 'w') do |file|
27
+ file.print content
28
+ end
29
+
30
+ Inkan.legitimate?('/tmp/spec.txt').should be_false
31
+ end
32
+ end
33
+
34
+ describe '.seal' do
35
+ it "should write the file after closing the block" do
36
+ Inkan.seal('/tmp/spec.txt') do |inkan|
37
+ inkan.print 'foo bar baz'
38
+ end
39
+
40
+ contents = open('/tmp/spec.txt').read
41
+ contents.should match(/foo bar baz$/)
42
+ contents.should match(/^# Generated by Inkan/)
43
+ end
44
+ end
45
+
46
+ describe '#seal' do
47
+ let(:inkan) { Inkan.new('/tmp/spec.txt') }
48
+
49
+ it "writes out the contents of the buffer" do
50
+ inkan.print "foo bar baz"
51
+ inkan.seal
52
+
53
+ open('/tmp/spec.txt').read.should match(/foo bar baz$/)
54
+ end
55
+
56
+ it "adds the credit line to the top of the file" do
57
+ inkan.print "foo bar baz"
58
+ inkan.seal
59
+
60
+ open('/tmp/spec.txt').read.should match(/^# Generated by Inkan/)
61
+ end
62
+
63
+ it "adds the SHA to the top of the file" do
64
+ inkan.print "foo bar baz"
65
+ inkan.seal
66
+
67
+ sha = Digest::SHA1.hexdigest("foo bar baz")
68
+
69
+ open('/tmp/spec.txt').read.should match(/#{sha}/)
70
+ end
71
+ end
72
+
73
+ describe '#puts' do
74
+ let(:inkan) { Inkan.new('/tmp/spec.txt') }
75
+
76
+ it "adds an extra new line to the output" do
77
+ inkan.puts "foo bar baz"
78
+ inkan.seal
79
+
80
+ open('/tmp/spec.txt').read.should match(/foo bar baz\n$/)
81
+ end
82
+ end
83
+
84
+ describe '#credit' do
85
+ let(:inkan) { Inkan.new('/tmp/spec.txt') }
86
+
87
+ it "defaults to 'Generated by Inkan'" do
88
+ inkan.credit.should == 'Generated by Inkan'
89
+ end
90
+
91
+ it "should pass through changes to the file comment" do
92
+ inkan.credit = "Pat's Magic Code"
93
+ inkan.print "foo bar baz"
94
+ inkan.seal
95
+
96
+ open('/tmp/spec.txt').read.should match(/^# Pat's Magic Code/)
97
+ end
98
+ end
99
+
100
+ describe '#comment' do
101
+ let(:inkan) { Inkan.new('/tmp/spec.txt') }
102
+
103
+ it "defaults to a hash symbol" do
104
+ inkan.comment.should == '#'
105
+ end
106
+
107
+ it "should pass through changes to the file credit" do
108
+ inkan.comment = "//"
109
+ inkan.print "foo bar baz"
110
+ inkan.seal
111
+
112
+ open('/tmp/spec.txt').read.should match(/^\/\/ Generated by Inkan/)
113
+ end
114
+ end
115
+
116
+ describe '#comment_suffix' do
117
+ let(:inkan) { Inkan.new('/tmp/spec.txt') }
118
+
119
+ it "defaults to a blank string" do
120
+ inkan.comment_suffix.should == ''
121
+ end
122
+
123
+ it "should pass through changes to the file comment" do
124
+ inkan.comment_suffix = "*/"
125
+ inkan.print "foo bar baz"
126
+ inkan.seal
127
+
128
+ open('/tmp/spec.txt').read.should match(/\*\/\n/)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'rubygems'
5
+ require 'bundler'
6
+
7
+ Bundler.require :default, :development
8
+
9
+ require 'inkan'
10
+
11
+ RSpec.configure do |config|
12
+
13
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inkan
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Pat Allan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-14 00:00:00 +08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :development
23
+ prerelease: false
24
+ name: jeweler
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - "="
29
+ - !ruby/object:Gem::Version
30
+ hash: -1876988220
31
+ segments:
32
+ - 1
33
+ - 5
34
+ - 0
35
+ - pre5
36
+ version: 1.5.0.pre5
37
+ requirement: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ type: :development
40
+ prerelease: false
41
+ name: yard
42
+ version_requirements: &id002 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - "="
46
+ - !ruby/object:Gem::Version
47
+ hash: 5
48
+ segments:
49
+ - 0
50
+ - 6
51
+ - 1
52
+ version: 0.6.1
53
+ requirement: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ type: :development
56
+ prerelease: false
57
+ name: rspec
58
+ version_requirements: &id003 !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - "="
62
+ - !ruby/object:Gem::Version
63
+ hash: 13
64
+ segments:
65
+ - 2
66
+ - 0
67
+ - 1
68
+ version: 2.0.1
69
+ requirement: *id003
70
+ - !ruby/object:Gem::Dependency
71
+ type: :development
72
+ prerelease: false
73
+ name: rcov
74
+ version_requirements: &id004 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - "="
78
+ - !ruby/object:Gem::Version
79
+ hash: 43
80
+ segments:
81
+ - 0
82
+ - 9
83
+ - 8
84
+ version: 0.9.8
85
+ requirement: *id004
86
+ description: ""
87
+ email: pat@freelancing-gods.com
88
+ executables: []
89
+
90
+ extensions: []
91
+
92
+ extra_rdoc_files:
93
+ - README.textile
94
+ files:
95
+ - LICENCE
96
+ - README.textile
97
+ - lib/inkan.rb
98
+ - spec/inkan_spec.rb
99
+ - spec/spec_helper.rb
100
+ has_rdoc: true
101
+ homepage: http://github.com/freelancing-god/inkan
102
+ licenses: []
103
+
104
+ post_install_message:
105
+ rdoc_options: []
106
+
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ hash: 3
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ hash: 3
124
+ segments:
125
+ - 0
126
+ version: "0"
127
+ requirements: []
128
+
129
+ rubyforge_project:
130
+ rubygems_version: 1.3.7
131
+ signing_key:
132
+ specification_version: 3
133
+ summary: Unique file markers for tracking whether files have been changed.
134
+ test_files:
135
+ - spec/inkan_spec.rb
136
+ - spec/spec_helper.rb