ignorance 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ignorance.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Joel Helbling
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # Ignorance
2
+
3
+ Ensures specified files are ignored by Git, Mercurial or SVN.
4
+
5
+ ## Use Case
6
+
7
+ You've created a utility to be used by others' projects which generates
8
+ or uses files and directories which ought not be committed/pushed/shared
9
+ with the world.
10
+
11
+ Ignorance helps your code be considerate of its users by protecting
12
+ their sensitive information.
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'ignorance'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install ignorance
27
+
28
+ ## Usage
29
+
30
+ If you'd like to warn users and fellow developers to add certain artifacts
31
+ to the project's ignore file, you can include this somewhere in your runtime:
32
+
33
+ ```ruby
34
+ include Ignorance
35
+
36
+ advise_ignorance '.myfile'
37
+ ```
38
+
39
+ Assuming those files are not in the project's .gitignore file, when
40
+ the code is run, your program will output the following to STDERR
41
+ (but not halt):
42
+
43
+ ```
44
+ WARNING: please add ".myfile" to this project's .gitignore file!
45
+ ```
46
+
47
+ If ignoring those files is really critical, you can halt with an exception:
48
+
49
+ ```ruby
50
+ guard_ignorance 'mydir/'
51
+ ```
52
+
53
+ You can even prompt the user, offering to automatically add the pertinent
54
+ files to the ignore file:
55
+
56
+ ```ruby
57
+ negotiate_ignorance 'some_file.md'
58
+ ```
59
+
60
+ And finally, if ignorance is absolutely critical, you can silently add
61
+ tokens to the project's ignore file:
62
+
63
+ ```ruby
64
+ guarantee_ignorance! 'mydir/'
65
+ ```
66
+
67
+ You can also use Ignorance directly (with out including the module).
68
+ Shorter method names are provided for that purpose:
69
+
70
+ ```ruby
71
+ Ignorance.advise '.myfile'
72
+ Ignorance.guard 'some_other_file.txt'
73
+ Ignorance.negotiate 'family_phone_numbers.yaml'
74
+ Ignorance.guarantee! 'bank_login.cfg'
75
+ ```
76
+
77
+ ## When Ignorance Works
78
+
79
+ Ignorance works on the ignore files of any and all detected repository types.
80
+ If .git is present, .gitignore is managed. If .hg then .hgignore,
81
+ if .svn, .svnignore. For Git and Mercurial, parent directories will also
82
+ be searched for a repository root.
83
+
84
+ Ignorance does nothing when one of two conditions exist:
85
+
86
+ 1. All specified tokens are already ignored
87
+ 2. The current directory is not within a repository
88
+
89
+ Ignorance's repo detection is based on the current working directory (e.g.
90
+ Dir.getwd, usually the directory where the code was launched). It presumes
91
+ the common dev-time situation wherein a program is launched from within its
92
+ project dir.
93
+
94
+ This means that if your code uses Ignorance, and others use your code, repo
95
+ and ignore file detection will happen relative to their project directory.
96
+
97
+ ## Adding a Comment
98
+
99
+ The #negotiate and #guarantee! methods (and their longer counterparts)
100
+ accept an optional comment parameter:
101
+
102
+ ```ruby
103
+ negotiate_ignorance 'api_token.yml', 'added by HandyBankUtil'
104
+ ```
105
+
106
+ This will add the following to the ignore file (assuming 'api_token.yml'
107
+ wasn't already ignored):
108
+
109
+ ```
110
+ # added by HandyBankUtil
111
+ api_token.yml
112
+
113
+ ```
114
+
115
+ If the supplied comment was already in the ignore file (suppose you
116
+ negotiated several tokens with the same comment), the new token will be
117
+ added to the bottom of that section. So if the ignore file already had
118
+ this:
119
+
120
+ ```
121
+ # added by HandyBankUtil
122
+ secret_info.txt
123
+
124
+ ```
125
+
126
+ The above example would result in this in the ignore file:
127
+
128
+ ```
129
+ # added by HandyBankUtil
130
+ secret_info.txt
131
+ api_token.yml
132
+
133
+ ```
134
+
135
+ ## Contributing
136
+
137
+ 1. Fork it
138
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
139
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
140
+ 4. Push to the branch (`git push origin my-new-feature`)
141
+ 5. Create new Pull Request
142
+
143
+ ## Do you love Ignorance, and want to make it even better?
144
+
145
+ Here's some stuff I ain't figured out yet:
146
+
147
+ - *Support for globs & regexes*: If you `gaurd_ignorance 'myfile.private'` and
148
+ the ignore file contains a glob or regex which would cause that to be ignored,
149
+ Ignorance will raise an error anyway.
150
+ - *Support for other version control systems.* Visual SourceSafe can't use
151
+ Ignorance. Does that seem right to you?
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/ignorance.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ignorance/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "ignorance"
8
+ gem.version = Ignorance::VERSION
9
+ gem.authors = ["Joel Helbling"]
10
+ gem.email = ["joel@joelhelbling.com"]
11
+ gem.description = %q{Ensures specified files are ignored by Git, Mercurial or SVN.}
12
+ gem.summary = %q{Ignorance helps your code be considerate of its users by protecting sensitive information from version control.}
13
+ gem.homepage = "http://github.com/joelhelbling/ignorance"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'highline', '~> 1.6.15'
21
+
22
+ gem.add_development_dependency 'rspec', '~> 2.12.0'
23
+ gem.add_development_dependency 'fakefs', '~> 0.4.2'
24
+ gem.add_development_dependency 'pry', '~> 0.9.11.4'
25
+ end
data/lib/ignorance.rb ADDED
@@ -0,0 +1,85 @@
1
+ require 'highline'
2
+ require 'ignorance/version'
3
+
4
+ require 'ignorance/git_ignore_file'
5
+ require 'ignorance/hg_ignore_file'
6
+ require 'ignorance/svn_ignore_file'
7
+
8
+ module Ignorance
9
+
10
+ class << self
11
+ def advise(token)
12
+ active_ignore_files.each do |ignore_file|
13
+ warning token, ignore_file unless ignore_file.ignored?(token)
14
+ end
15
+ end
16
+
17
+ def guard(token)
18
+ active_ignore_files.each do |ignore_file|
19
+ unless ignore_file.ignored?(token)
20
+ raise IgnorefileError.new "Please add \"#{token}\" to this project's #{ignore_file.name} file!"
21
+ end
22
+ end
23
+ end
24
+
25
+ def negotiate(token, comment=nil)
26
+ active_ignore_files.each do |ignore_file|
27
+ unless ignore_file.ignored?(token)
28
+ msg = "would you like me to add #{token} to this project's #{ignore_file.name} file automatically?"
29
+ if agree? msg
30
+ guarantee! token, comment
31
+ puts "Added \"#{token}\" to this project's #{ignore_file.name} file."
32
+ else
33
+ warning token, ignore_file
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def guarantee!(token, comment=nil)
40
+ active_ignore_files.each do |ignore_file|
41
+ unless ignore_file.ignored?(token)
42
+ ignore_file.ignore! token, comment
43
+ end
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def warning(token, ignore_file)
50
+ warn "WARNING: please add \"#{token}\" to this project's #{ignore_file.name} file!"
51
+ end
52
+
53
+ def active_ignore_files
54
+ ignore_files.select(&:its_a_repo?)
55
+ end
56
+
57
+ def ignore_files
58
+ [GitIgnoreFile.new, HgIgnoreFile.new, SvnIgnoreFile.new]
59
+ end
60
+
61
+ def agree?(msg)
62
+ HighLine.new.agree("#{msg} [Y]es/[n]o? ")
63
+ end
64
+
65
+ end
66
+
67
+ def advise_ignorance(token)
68
+ Ignorance.advise token, comment
69
+ end
70
+
71
+ def guard_ignorance(token)
72
+ Ignorance.guard token, comment
73
+ end
74
+
75
+ def negotiate_ignorance(token, comment=nil)
76
+ Ignorance.negotiate token, comment
77
+ end
78
+
79
+ def guarantee_ignorance!(token, comment=nil)
80
+ Ignorance.guarantee! token, comment
81
+ end
82
+
83
+ class IgnorefileError < IOError; end
84
+
85
+ end
@@ -0,0 +1,33 @@
1
+ require 'ignorance/ignore_file'
2
+ require 'ignorance/project_oriented_vcs'
3
+
4
+ module Ignorance
5
+ class GitIgnoreFile < IgnoreFile
6
+ attr_reader :ignore_file, :repo_dir
7
+
8
+ include ProjectOrientedVCS
9
+
10
+ def initialize
11
+ @ignore_file = '.gitignore'
12
+ @repo_dir = '.git'
13
+ end
14
+
15
+ private
16
+
17
+ def ignored
18
+ (file_contents + user_ignore_file_contents).reject do |t|
19
+ t.match /^\#/
20
+ end.map(&:chomp)
21
+ end
22
+
23
+ def user_ignore_file_contents
24
+ File.exists?(user_ignore_file) ? File.readlines(user_ignore_file) : []
25
+ end
26
+
27
+ def user_ignore_file
28
+ @user_ignore_file ||= `git config --global --get core.excludesfile`.chomp
29
+ end
30
+
31
+ end
32
+ end
33
+
@@ -0,0 +1,16 @@
1
+ require 'ignorance/ignore_file'
2
+ require 'ignorance/project_oriented_vcs'
3
+
4
+ module Ignorance
5
+ class HgIgnoreFile < IgnoreFile
6
+ attr_reader :ignore_file, :repo_dir
7
+
8
+ include ProjectOrientedVCS
9
+
10
+ def initialize
11
+ @ignore_file = '.hgignore'
12
+ @repo_dir = '.hg'
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,96 @@
1
+ module Ignorance
2
+ class IgnoreFile
3
+
4
+ def name
5
+ ignore_file
6
+ end
7
+
8
+ def exists?
9
+ File.exists? ignore_file
10
+ end
11
+
12
+ def its_a_repo?
13
+ Dir.exists? repo_dir
14
+ end
15
+
16
+ def ignored?(token)
17
+ ignored.include? token
18
+ end
19
+
20
+ def included?(token)
21
+ file_contents.include? token
22
+ end
23
+
24
+ def ignore!(token, comment=nil)
25
+ return true if ignored?(token)
26
+ if comment
27
+ anchor = commentified comment
28
+ if included? anchor
29
+ insert_after anchor, token
30
+ else
31
+ append "\n"
32
+ append anchor
33
+ append token
34
+ end
35
+ else # There's no comment
36
+ append token
37
+ end
38
+
39
+ write_ignore_file
40
+ end
41
+
42
+ private
43
+
44
+ def ignored
45
+ file_contents.reject{ |t| t.match /^\#/ }.map(&:chomp)
46
+ end
47
+
48
+ def file_contents
49
+ @file_contents ||= exists? ? File.readlines(ignore_file) : []
50
+ end
51
+
52
+ def insert_at(index, token)
53
+ file_contents.insert(index, token)
54
+ end
55
+
56
+ def append(token)
57
+ insert_at(file_contents.size, token)
58
+ end
59
+
60
+ def insert_after(anchor, token)
61
+ insert_index = file_contents.find_index(anchor) + 1
62
+ insert_index += 1 until here_is_good?(insert_index)
63
+ insert_at insert_index, token
64
+ end
65
+
66
+ def here_is_good?(insert_index)
67
+ at_maximum?(insert_index) || blank_line_at?(insert_index)
68
+ end
69
+
70
+ def at_maximum?(insert_index)
71
+ insert_index >= file_contents.size
72
+ end
73
+
74
+ def blank_line_at?(insert_index)
75
+ file_contents[insert_index].match(/^[\s\n]*$/)
76
+ end
77
+
78
+ def commentified(comment)
79
+ "# " + comment.gsub(/^\s*\#\s*/, '')
80
+ end
81
+
82
+ def printified(line)
83
+ line.chomp + "\n"
84
+ end
85
+
86
+ def write_ignore_file
87
+ File.open(ignore_file, 'w') do |fh|
88
+ file_contents.each do |line|
89
+ fh.write printified line
90
+ end
91
+ end
92
+ end
93
+
94
+ end
95
+ end
96
+
@@ -0,0 +1,14 @@
1
+ module Ignorance
2
+ module ProjectOrientedVCS
3
+
4
+ def its_a_repo?
5
+ path = Dir.getwd.scan(/\/[^\/]+/).map{|p| p[1..-1]}
6
+ repo_found = false
7
+ until (repo_found = Dir.exists?(File.join("/", path, @repo_dir))) || path.empty?
8
+ path.pop
9
+ end
10
+ repo_found
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'ignorance/ignore_file'
2
+
3
+ module Ignorance
4
+ class SvnIgnoreFile < IgnoreFile
5
+ attr_reader :ignore_file, :repo_dir
6
+
7
+ def initialize
8
+ @ignore_file = '.svnignore'
9
+ @repo_dir = '.svn'
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Ignorance
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ module IgnorefileHelpers
2
+
3
+ def ignorefile_write(contents)
4
+ File.open(ignore_file, 'w') do |fh|
5
+ fh.write contents
6
+ end
7
+ end
8
+
9
+ def ignorefile_lines
10
+ File.readlines(ignore_file)
11
+ end
12
+
13
+ def ignored_tokens
14
+ ignorefile_lines.map(&:chomp)
15
+ end
16
+
17
+ def ignorefile_contents
18
+ File.read(ignore_file)
19
+ end
20
+
21
+ def mk_repo_dir
22
+ Dir.mkdir repo_dir
23
+ end
24
+
25
+ end
@@ -0,0 +1,32 @@
1
+ require 'stringio'
2
+
3
+ module IOHelpers
4
+
5
+ def output_from
6
+ $stdout = $stderr = fake_io
7
+ yield
8
+ fake_io.string
9
+ ensure
10
+ $stdout = STDOUT; $stderr = STDERR
11
+ end
12
+
13
+ def user_types(input, &block)
14
+ $stdin = StringIO.new input
15
+ output_from &block
16
+ ensure
17
+ $stdin = STDIN
18
+ end
19
+
20
+ def stdout_from(&block)
21
+ output_from &block
22
+ end
23
+
24
+ def stderr_from(&block)
25
+ output_from &block
26
+ end
27
+
28
+ def fake_io
29
+ @fake_io ||= StringIO.new
30
+ end
31
+
32
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'ignorance/git_ignore_file'
3
+
4
+ module Ignorance
5
+ describe GitIgnoreFile, :fakefs do
6
+
7
+ let(:ignore_file) { '.gitignore' }
8
+ let(:repo_dir) { '.git' }
9
+
10
+ it_should_behave_like "an ignore file"
11
+ it_should_behave_like "a project-oriented VCS"
12
+
13
+ context "when the user's gitignore file includes the token" do
14
+ let(:token) { "foofile.md" }
15
+ let(:user_ignore_file) { '~/.gitignore' }
16
+ before do
17
+ ignorefile_write %w[other stuff here].join("\n")
18
+ File.open(user_ignore_file, 'w') do |fh|
19
+ fh.write "#{token}\n"
20
+ end
21
+ subject.stub(:user_ignore_file).and_return(user_ignore_file)
22
+ end
23
+
24
+ specify "then the file is ignored" do
25
+ File.read('~/.gitignore').should match /#{token}/
26
+ subject.ignored?(token).should be_true
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'ignorance/hg_ignore_file'
3
+
4
+ module Ignorance
5
+ describe HgIgnoreFile, :fakefs do
6
+
7
+ let(:ignore_file) { '.hgignore' }
8
+ let(:repo_dir) { '.hg' }
9
+
10
+ it_should_behave_like "an ignore file"
11
+ it_should_behave_like "a project-oriented VCS"
12
+
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+ require 'ignorance/ignore_file'
3
+ require 'ignorance/git_ignore_file'
4
+
5
+ module Ignorance
6
+ describe IgnoreFile do
7
+
8
+ it { should respond_to :name, :exists?, :its_a_repo?, :ignored?, :ignore! }
9
+
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'ignorance/svn_ignore_file'
3
+
4
+ module Ignorance
5
+ describe SvnIgnoreFile, :fakefs do
6
+
7
+ let(:ignore_file) { '.svnignore' }
8
+ let(:repo_dir) { '.svn' }
9
+
10
+ it_should_behave_like "an ignore file"
11
+
12
+ end
13
+ end
14
+
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'ignorance'
3
+
4
+ describe Ignorance do
5
+
6
+ describe "class methods (e.g. Ingorance.guard...)" do
7
+ subject { Ignorance }
8
+ it { should respond_to :advise, :guard, :negotiate, :guarantee! }
9
+ end
10
+
11
+ describe "when included" do
12
+ before do
13
+ class TestIncluder
14
+ include Ignorance
15
+ end
16
+ end
17
+ subject { TestIncluder.new }
18
+
19
+ it do
20
+ should respond_to :advise_ignorance,
21
+ :guard_ignorance,
22
+ :negotiate_ignorance,
23
+ :guarantee_ignorance!
24
+ end
25
+ end
26
+
27
+ context "with Git" do
28
+ let(:ignore_file) { '.gitignore' }
29
+ let(:repo_dir) { '.git' }
30
+
31
+ it_should_behave_like Ignorance
32
+ end
33
+
34
+ context "with Mercurial" do
35
+ let(:ignore_file) { '.hgignore' }
36
+ let(:repo_dir) { '.hg' }
37
+
38
+ it_should_behave_like Ignorance
39
+
40
+ end
41
+
42
+ context "with SVN" do
43
+ let(:ignore_file) { '.svnignore' }
44
+ let(:repo_dir) { '.svn' }
45
+
46
+ it_should_behave_like Ignorance
47
+
48
+ end
49
+ end
@@ -0,0 +1,93 @@
1
+ shared_examples Ignorance do
2
+
3
+ context "So anyway...", :fakefs do
4
+ before { mk_repo_dir }
5
+ let(:token) { "foo.rb" }
6
+
7
+ describe "::advise", :capture_io do
8
+
9
+ context "token is already in ignore file" do
10
+ before { ignorefile_write "#{token}\n" }
11
+
12
+ it "does not warn" do
13
+ expect( stderr_from { Ignorance.advise token } ).to be_empty
14
+ end
15
+ end
16
+
17
+ context "token is NOT in ignore file" do
18
+ before { ignorefile_write "something-else.txt\n" }
19
+
20
+ it "prints warn (STDERR)" do
21
+ expect( stderr_from { Ignorance.advise token } ).to match /WARNING:.*add "#{token}" to .*#{ignore_file}/
22
+ end
23
+ end
24
+ end
25
+
26
+ describe "::guard" do
27
+ context "token is already in ignore file" do
28
+ before { ignorefile_write "#{token}\n" }
29
+
30
+ specify "no error is raised" do
31
+ expect { Ignorance.guard token }.to_not raise_error
32
+ end
33
+ end
34
+
35
+ context "token is NOT in ignore file" do
36
+ before { ignorefile_write "something-else.txt\n" }
37
+
38
+ it "raises an error" do
39
+ expect { Ignorance.guard token }.to raise_error Ignorance::IgnorefileError, /add "#{token}" to .*#{ignore_file}/
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "::negotiate", :capture_io do
45
+
46
+ context "token is already in ignore file" do
47
+ before { ignorefile_write "#{token}\n" }
48
+
49
+ it "does nothing" do
50
+ expect( stdout_from { Ignorance.negotiate token } ).to be_empty
51
+ end
52
+ end
53
+
54
+ context "token is NOT in ignore file" do
55
+ before { ignorefile_write "stuff.txt\n" }
56
+
57
+ context "user agrees (y)" do
58
+ specify do
59
+ expect( user_types("y") { Ignorance.negotiate token } ).to match /added "#{token}"/i
60
+ end
61
+ end
62
+
63
+ context "user disagrees (n)" do
64
+ specify do
65
+ expect( user_types("n") { Ignorance.negotiate token } ).to match /WARNING:.*add "#{token}" to .*#{ignore_file}/
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "::guarantee!" do
72
+ context "token is already in ignore file" do
73
+ before { ignorefile_write "#{token}\n" }
74
+
75
+ it "does not change the ignore file" do
76
+ Ignorance.guarantee! token, "a comment"
77
+ ignorefile_contents.should == "#{token}\n"
78
+ end
79
+ end
80
+
81
+ context "token is NOT in ignore file" do
82
+ before { ignorefile_write "stuff.txt\n" }
83
+
84
+ it "adds to the ignore file" do
85
+ Ignorance.guarantee! token, "a comment"
86
+ ignorefile_contents.should == "stuff.txt\n\n# a comment\n#{token}\n"
87
+ end
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,147 @@
1
+ module Ignorance
2
+ shared_examples "an ignore file" do
3
+
4
+ it { should respond_to :name, :exists?, :its_a_repo?, :ignored?, :ignore! }
5
+ its(:name) { should == ignore_file }
6
+
7
+ describe "#exists?" do
8
+
9
+ context "when the ignore file does NOT exist" do
10
+ it { should_not exist }
11
+ end
12
+
13
+ context "when the ignore file DOES exist" do
14
+ before { ignorefile_write "" }
15
+ it { should exist }
16
+ end
17
+
18
+ end
19
+
20
+
21
+ describe "#its_a_repo?" do
22
+
23
+ context "when the repo subdirectory does NOT exist" do
24
+ it { should_not be_its_a_repo }
25
+ end
26
+
27
+ context "when the repo subdirectory DOES exist" do
28
+ before { Dir.mkdir repo_dir }
29
+ it { should be_its_a_repo }
30
+ end
31
+
32
+ end
33
+
34
+ describe "#ignored?" do
35
+ let(:token) { "foofile.txt" }
36
+
37
+ context "when the ignore file doesn't exist" do
38
+ specify "then the file is not ignored, duh" do
39
+ subject.should_not exist
40
+ subject.ignored?(token).should == false
41
+ end
42
+ end
43
+
44
+ context "when the ignore file does exist" do
45
+
46
+ context "when the ignore file doesn't include the token" do
47
+ before { ignorefile_write %w[other stuff here].join("\n") }
48
+ it { should_not be_ignored(token) }
49
+ end
50
+
51
+ context "when the ignore file DOES include the token" do
52
+ before { ignorefile_write ["other", token+"", "stuff"].join("\n") }
53
+ it { should be_ignored(token) }
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+
60
+ describe "#ignore!" do
61
+ let(:token) { "foofile.txt" }
62
+
63
+ context "there is no ignore file" do
64
+ it "writes to the ignore file" do
65
+ subject.should_not exist
66
+ subject.ignore! token
67
+ ignored_tokens.should include token
68
+ end
69
+ end
70
+
71
+ context "there is already an ignore file" do
72
+ before { ignorefile_write "*.swp\n" }
73
+ specify do
74
+ ignored_tokens.should include '*.swp'
75
+ subject.ignore! token
76
+ ignored_tokens.should include '*.swp'
77
+ end
78
+ end
79
+
80
+ context "the token is already in the ignore file" do
81
+ let(:content) { "other\n#{token}\nstuff\n" }
82
+ before { ignorefile_write content }
83
+
84
+ it "doesn't write to the ignore file" do
85
+ File.any_instance.should_not_receive(:write)
86
+ subject.ignore!(token)
87
+ ignored_tokens.should include token
88
+ end
89
+ end
90
+
91
+ context "with a comment" do
92
+ context "when the comment wasn't already in the file" do
93
+ specify do
94
+ subject.ignore! token, "# hide these files!"
95
+ ignorefile_contents.should match /# hide these files!\n#{token}\n/
96
+ end
97
+ end
98
+
99
+ context "when the comment was already in the file" do
100
+ let(:comment) { "hide these files!" }
101
+
102
+ context "comment is the last line of the file" do
103
+ before { ignorefile_write "\n# #{comment}\n" }
104
+
105
+ specify do
106
+ subject.ignore! token, comment
107
+ ignorefile_contents.should match /# #{comment}\n#{token}\n/
108
+ end
109
+ end
110
+
111
+ context "when the comment has other tokens after it" do
112
+ before do
113
+ ignorefile_write <<-IGNORE
114
+ # #{comment}
115
+ barfile.md
116
+
117
+ other-things
118
+ IGNORE
119
+ end
120
+ let(:expected) { Regexp.new /# #{comment}\nbarfile\.md\n#{token}\n\nother-things/ }
121
+
122
+ specify do
123
+ subject.ignore! token, comment
124
+ ignorefile_contents.should match expected
125
+ end
126
+ end
127
+
128
+ context "when comment has other tokens at end of file" do
129
+ before do
130
+ ignorefile_write <<-IGNORE
131
+ # #{comment}
132
+ barfile.md
133
+ IGNORE
134
+ end
135
+ let(:expected) { Regexp.new /# #{comment}\nbarfile\.md\n#{token}\n/ }
136
+
137
+ specify do
138
+ subject.ignore! token, comment
139
+ ignorefile_contents.should match expected
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
@@ -0,0 +1,26 @@
1
+ shared_examples "a project-oriented VCS" do
2
+
3
+ describe "#its_a_repo?", :fakefs do
4
+ context "pwd is a subdirectory of the repo root" do
5
+ before do
6
+ mk_repo_dir
7
+ Dir.mkdir 'lib'
8
+ Dir.mkdir 'lib/other'
9
+ Dir.chdir 'lib/other'
10
+ end
11
+
12
+ it { should be_its_a_repo }
13
+ end
14
+
15
+ context "pwd is not the subdirectory of any repo" do
16
+ before do
17
+ Dir.mkdir 'lib'
18
+ Dir.mkdir 'lib/other'
19
+ Dir.chdir 'lib/other'
20
+ end
21
+
22
+ it { should_not be_its_a_repo }
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,16 @@
1
+ require 'fakefs/spec_helpers'
2
+ require File.join(File.dirname(__FILE__), 'ignorefile_helpers')
3
+ require File.join(File.dirname(__FILE__), 'io_helpers')
4
+
5
+ here = File.dirname(__FILE__)
6
+
7
+ $LOAD_PATH.unshift(File.expand_path(File.join(here, '..', '..', 'lib')))
8
+
9
+ Dir[File.join(here, "shared_examples") + "/**/*.rb"].sort.map{|f| File.basename f }.map{|f| "shared_examples/#{f}"}.each {|f| require f}
10
+
11
+ RSpec.configure do |cfg|
12
+ cfg.treat_symbols_as_metadata_keys_with_true_values = true
13
+ cfg.include FakeFS::SpecHelpers, fakefs: true
14
+ cfg.include IgnorefileHelpers, fakefs: true
15
+ cfg.include IOHelpers, capture_io: true
16
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ignorance
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joel Helbling
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: highline
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.6.15
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.6.15
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 2.12.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.12.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: fakefs
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.4.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.4.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.9.11.4
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.9.11.4
78
+ description: Ensures specified files are ignored by Git, Mercurial or SVN.
79
+ email:
80
+ - joel@joelhelbling.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - Gemfile
87
+ - LICENSE.txt
88
+ - README.md
89
+ - Rakefile
90
+ - ignorance.gemspec
91
+ - lib/ignorance.rb
92
+ - lib/ignorance/git_ignore_file.rb
93
+ - lib/ignorance/hg_ignore_file.rb
94
+ - lib/ignorance/ignore_file.rb
95
+ - lib/ignorance/project_oriented_vcs.rb
96
+ - lib/ignorance/svn_ignore_file.rb
97
+ - lib/ignorance/version.rb
98
+ - spec/ignorefile_helpers.rb
99
+ - spec/io_helpers.rb
100
+ - spec/lib/ignorance/git_ignore_file_spec.rb
101
+ - spec/lib/ignorance/hg_ignore_file_spec.rb
102
+ - spec/lib/ignorance/ignore_file_spec.rb
103
+ - spec/lib/ignorance/svn_ignore_file_spec.rb
104
+ - spec/lib/ignorance_spec.rb
105
+ - spec/shared_examples/for_ignorance.rb
106
+ - spec/shared_examples/for_ignore_files.rb
107
+ - spec/shared_examples/for_project_oriented_vcs.rb
108
+ - spec/spec_helper.rb
109
+ homepage: http://github.com/joelhelbling/ignorance
110
+ licenses: []
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 1.8.24
130
+ signing_key:
131
+ specification_version: 3
132
+ summary: Ignorance helps your code be considerate of its users by protecting sensitive
133
+ information from version control.
134
+ test_files:
135
+ - spec/ignorefile_helpers.rb
136
+ - spec/io_helpers.rb
137
+ - spec/lib/ignorance/git_ignore_file_spec.rb
138
+ - spec/lib/ignorance/hg_ignore_file_spec.rb
139
+ - spec/lib/ignorance/ignore_file_spec.rb
140
+ - spec/lib/ignorance/svn_ignore_file_spec.rb
141
+ - spec/lib/ignorance_spec.rb
142
+ - spec/shared_examples/for_ignorance.rb
143
+ - spec/shared_examples/for_ignore_files.rb
144
+ - spec/shared_examples/for_project_oriented_vcs.rb
145
+ - spec/spec_helper.rb