ignorance 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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