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 +20 -0
- data/README.textile +54 -0
- data/lib/inkan.rb +60 -0
- data/spec/inkan_spec.rb +131 -0
- data/spec/spec_helper.rb +13 -0
- metadata +136 -0
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.
|
data/README.textile
ADDED
@@ -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.
|
data/lib/inkan.rb
ADDED
@@ -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
|
data/spec/inkan_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|