gemignore 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ --private -m markdown
data/Changelog CHANGED
@@ -1,3 +1,19 @@
1
+ == 0.4.0
2
+ * Add shortcuts for gemignore commands
3
+ * Switch to GitHub API v3 (using Octokit)
4
+ * Add request caching for better performance
5
+ * Add support for searching and adding multiple snippets at once
6
+ * Table-like output for "list" and "search" commands
7
+ * Add slightly better error handling (e.g. no internet connection)
8
+ * Add new "peek" subcommand to look at a snippet without adding it
9
+
10
+ == 0.3.0
11
+ * Fix bugs that prevented certain snippets from being added
12
+ * Add unit tests for adding snippets
13
+
14
+ == 0.2.1
15
+ * Fix compatibility issues with new GitHub API
16
+
1
17
  == 0.2.0
2
18
  * Add colored messages
3
19
  * Fix bug which prevented one from installing the 'Go' snippet
@@ -5,4 +21,4 @@
5
21
  * Add usage information accessible from command line
6
22
 
7
23
  == 0.1.1
8
- * First release
24
+ * First release
data/Gemfile CHANGED
@@ -4,12 +4,14 @@ source "http://rubygems.org"
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
  gem "json", ">= 1.5.1"
6
6
  gem "rainbow", "~> 1.1.1"
7
+ gem "octokit", "~> 1.0.5"
8
+ gem "terminal-table", "~> 1.4.5"
9
+ gem "ruby-terminfo", "~> 0.1.1"
7
10
 
8
11
  # Add dependencies to develop your gem here.
9
12
  # Include everything needed to run rake, tests, features, etc.
10
13
  group :development do
11
- gem "rspec", "~> 2.3.0"
12
- gem "bundler", "~> 1.0.0"
14
+ gem "rspec", "~> 2.10.0"
15
+ gem "bundler", "~> 1.1.0"
13
16
  gem "jeweler", "~> 1.6.0"
14
- gem "rcov", ">= 0"
15
17
  end
@@ -0,0 +1,40 @@
1
+ # gemignore
2
+
3
+ This is a handy little tool for all people who work with Git. It allows you to easily add .gitignore snippets to the .gitignore file in your current working directory. The snippets are taken from https://github.com/github/gitignore , so if there is anything missing, feel free to fork that repository and create a pull request :)
4
+
5
+ # Installation
6
+
7
+ $ gem install gemignore
8
+
9
+ # Usage
10
+
11
+ To search for a .gitignore snippet, simply type
12
+
13
+ $ gemignore search lin # or
14
+ $ gemignore s lin
15
+
16
+ To list all available snippets run
17
+
18
+ $ gemignore list # or
19
+ $ gemignore l
20
+
21
+ And finally, to add a snippet to the .gitignore file in the **current working directory**:
22
+
23
+ $ gemignore add Global/OSX # or
24
+ $ gemignore a osx
25
+
26
+ To display usage information you can use
27
+
28
+ $ gemignore help
29
+
30
+
31
+ # Licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php)
32
+
33
+ Copyright (c) 2012 Lucas Jenß
34
+
35
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
36
+
37
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40
+
data/Rakefile CHANGED
@@ -39,7 +39,7 @@ end
39
39
 
40
40
  task :default => :spec
41
41
 
42
- require 'rake/rdoctask'
42
+ require 'rdoc/task'
43
43
  Rake::RDocTask.new do |rdoc|
44
44
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
45
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -5,4 +5,4 @@ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
5
 
6
6
  require 'gemignore'
7
7
 
8
- GemIgnore::Main.new.dispatch
8
+ GemIgnore::Main.new.dispatchWithErrorHandling
@@ -4,43 +4,42 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{gemignore}
8
- s.version = "0.3.0"
7
+ s.name = "gemignore"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = [%q{Lucas Jenss}]
12
- s.date = %q{2011-11-06}
13
- s.description = %q{gemignore allows you to automatically insert a wide range of preset .gitignore snippets into your .gitignore files}
14
- s.email = %q{lucas@x3ro.de}
15
- s.executables = [%q{gemignore}]
11
+ s.authors = ["Lucas Jenss"]
12
+ s.date = "2012-05-24"
13
+ s.description = "gemignore allows you to automatically insert a wide range of preset .gitignore snippets into your .gitignore files"
14
+ s.email = "lucas@x3ro.de"
15
+ s.executables = ["gemignore"]
16
16
  s.extra_rdoc_files = [
17
- "LICENSE.txt",
18
- "README.rdoc"
17
+ "README.md"
19
18
  ]
20
19
  s.files = [
21
20
  ".document",
22
21
  ".rspec",
22
+ ".yardopts",
23
23
  "Changelog",
24
24
  "Gemfile",
25
- "LICENSE.txt",
26
- "README.rdoc",
25
+ "README.md",
27
26
  "Rakefile",
28
27
  "VERSION",
29
28
  "bin/.gitignore",
30
29
  "bin/gemignore",
31
30
  "gemignore.gemspec",
32
31
  "lib/gemignore.rb",
32
+ "lib/gemignore/github.rb",
33
33
  "lib/gemignore/main.rb",
34
34
  "lib/gemignore/util.rb",
35
35
  "spec/gemignore_spec.rb",
36
- "spec/spec_helper.rb",
37
- "tests/gemignore_add_test.rb"
36
+ "spec/spec_helper.rb"
38
37
  ]
39
- s.homepage = %q{http://coding-journal.com/hassle-free-gitignore-management-with-gemignore/}
40
- s.licenses = [%q{MIT}]
41
- s.require_paths = [%q{lib}]
42
- s.rubygems_version = %q{1.8.6}
43
- s.summary = %q{A command-line tool which ought to simplify your daily .gitignore hassle}
38
+ s.homepage = "http://coding-journal.com/hassle-free-gitignore-management-with-gemignore/"
39
+ s.licenses = ["MIT"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = "1.8.21"
42
+ s.summary = "A command-line tool which ought to simplify your daily .gitignore hassle"
44
43
 
45
44
  if s.respond_to? :specification_version then
46
45
  s.specification_version = 3
@@ -48,25 +47,31 @@ Gem::Specification.new do |s|
48
47
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
48
  s.add_runtime_dependency(%q<json>, [">= 1.5.1"])
50
49
  s.add_runtime_dependency(%q<rainbow>, ["~> 1.1.1"])
51
- s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
52
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
50
+ s.add_runtime_dependency(%q<octokit>, ["~> 1.0.5"])
51
+ s.add_runtime_dependency(%q<terminal-table>, ["~> 1.4.5"])
52
+ s.add_runtime_dependency(%q<ruby-terminfo>, ["~> 0.1.1"])
53
+ s.add_development_dependency(%q<rspec>, ["~> 2.10.0"])
54
+ s.add_development_dependency(%q<bundler>, ["~> 1.1.0"])
53
55
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
54
- s.add_development_dependency(%q<rcov>, [">= 0"])
55
56
  else
56
57
  s.add_dependency(%q<json>, [">= 1.5.1"])
57
58
  s.add_dependency(%q<rainbow>, ["~> 1.1.1"])
58
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
59
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
+ s.add_dependency(%q<octokit>, ["~> 1.0.5"])
60
+ s.add_dependency(%q<terminal-table>, ["~> 1.4.5"])
61
+ s.add_dependency(%q<ruby-terminfo>, ["~> 0.1.1"])
62
+ s.add_dependency(%q<rspec>, ["~> 2.10.0"])
63
+ s.add_dependency(%q<bundler>, ["~> 1.1.0"])
60
64
  s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
61
- s.add_dependency(%q<rcov>, [">= 0"])
62
65
  end
63
66
  else
64
67
  s.add_dependency(%q<json>, [">= 1.5.1"])
65
68
  s.add_dependency(%q<rainbow>, ["~> 1.1.1"])
66
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
67
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
69
+ s.add_dependency(%q<octokit>, ["~> 1.0.5"])
70
+ s.add_dependency(%q<terminal-table>, ["~> 1.4.5"])
71
+ s.add_dependency(%q<ruby-terminfo>, ["~> 0.1.1"])
72
+ s.add_dependency(%q<rspec>, ["~> 2.10.0"])
73
+ s.add_dependency(%q<bundler>, ["~> 1.1.0"])
68
74
  s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
69
- s.add_dependency(%q<rcov>, [">= 0"])
70
75
  end
71
76
  end
72
77
 
@@ -1,4 +1,9 @@
1
1
  module GemIgnore
2
2
  end
3
3
 
4
- require 'gemignore/main'
4
+ lib = File.expand_path(File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
6
+
7
+ require 'gemignore/util'
8
+ require 'gemignore/github'
9
+ require 'gemignore/main'
@@ -0,0 +1,98 @@
1
+ require 'octokit'
2
+ require 'base64'
3
+ require 'tmpdir'
4
+ require 'json'
5
+
6
+ # This class implements the necessary high-level operations we need to perform on the
7
+ # GitHub API and caches them. "High-level", because most of them are already pre-processed
8
+ # to fit what is needed in gemignore, whereas "low-level" operations are those directly
9
+ # performed on the GitHub API
10
+ #
11
+ class GitHub
12
+
13
+ CACHE_LIFETIME = 60 * 30 # seconds
14
+
15
+ # Path to our temporary cache file
16
+ @tmpFile = Dir.tmpdir + '/' + 'gemignoretemp'
17
+
18
+
19
+ # Try to load cache from temporary file
20
+ if File.exists? @tmpFile
21
+ @cache = JSON.parse(File.open(@tmpFile,'rb').read)
22
+ @cache = nil if (Time.now.to_i - @cache["creationTime"]) > CACHE_LIFETIME
23
+ end
24
+
25
+ @cache ||= { "creationTime" => Time.now.to_i }
26
+
27
+
28
+ class << self
29
+ # Path to the temporary file where we store our cache object. Necessary so that we can
30
+ # access the path in the finalizer.
31
+ #
32
+ attr_reader :tmpFile
33
+
34
+ # The object which is used to cache requests. Necessary so that we may access the cache
35
+ # object in the finalizer.
36
+ #
37
+ attr_reader :cache
38
+ end
39
+
40
+
41
+ # This finalizer is used to write the cache object to a temporary file when the program
42
+ # exits. We try to load the cache object from the file when this class is created.
43
+ #
44
+ ObjectSpace.define_finalizer(self, proc do
45
+ File.open(self.tmpFile, 'w').write(JSON.generate(self.cache))
46
+ end)
47
+
48
+
49
+ # Retrieve the full list of files available inside the given repository + tree.
50
+ #
51
+ def self.fileList(repo, tree_sha)
52
+ idArray = ["fileList", repo, tree_sha]
53
+ cache = readCache(idArray)
54
+ return cache if not cache.nil?
55
+
56
+ tree = Octokit.tree(repo, tree_sha, :recursive => 1).tree
57
+ writeCache(idArray, Hash[*tree.flat_map { |t| [t.path, t.sha] }])
58
+ end
59
+
60
+
61
+ # Retrieves a file's contents identified by its blob's SHA hash
62
+ #
63
+ def self.getFile(repo, sha)
64
+ idArray = ['getFile', repo, sha]
65
+ cache = readCache(idArray)
66
+ return cache if not cache.nil?
67
+
68
+ res = Octokit.blob(repo, sha)
69
+ data = nil
70
+ case res.encoding
71
+ when "base64"
72
+ data = Base64.decode64(res.content)
73
+ when "utf-8"
74
+ data = res.content
75
+ else
76
+ raise NotImplementedError.new("Could not decode response from GitHub API")
77
+ end
78
+ self.writeCache(idArray, data)
79
+ end
80
+
81
+
82
+ private
83
+
84
+ # Write a value to our cache object.
85
+ def self.writeCache(idArray, value)
86
+ raise ArgumentError.new("idArray parameter must be an array") if not idArray.is_a? Array
87
+ id = idArray.join("$")
88
+ @cache[id] = value
89
+ end
90
+
91
+
92
+ def self.readCache(idArray)
93
+ id = idArray.join("$")
94
+ @cache[id]
95
+ end
96
+
97
+ end
98
+
@@ -4,54 +4,91 @@ require 'net/http'
4
4
  require 'net/https'
5
5
  require 'json'
6
6
 
7
- require 'gemignore/util'
8
7
 
9
8
  module GemIgnore
10
9
 
11
- #--
12
- # FIXME: Not a good name, but for now its okay
13
- # FIXME: Add documentation
14
- # FIXME: Cleanup code
15
- #++
10
+ # This is where the core functionality of GemIgnore lies
16
11
  class Main
17
12
 
18
13
  include Util
19
14
 
20
- def dispatch
15
+ # Set the repository and branch where we want to retrieve the snippets from
16
+ def initialize
17
+ @snippetRepository = 'github/gitignore'
18
+ @snippetBranch = 'master'
19
+ end
20
+
21
+
22
+ # Default entry point when running from command line
23
+ def dispatchWithErrorHandling
24
+ debugMode = (not ARGV.delete("-d").nil?)
25
+
26
+ begin
27
+ dispatch(ARGV.dup)
28
+ rescue CommandError => e
29
+ raise e if debugMode
30
+ error e.message
31
+ help
32
+ exit
33
+ rescue Exception => e
34
+ raise e if debugMode
35
+ error "An error occured (are you connected to the internet?)"
36
+ error "For more information run gemignore with the '-d' option."
37
+ end
38
+ end
39
+
21
40
 
22
- (help; return) if ARGV.length === 0
41
+ # Invokes the correct method according to the command line options that were given
42
+ def dispatch(arguments)
43
+ raise CommandError.new("Not enough arguments given.") if arguments.empty?
23
44
 
24
- cmd = ARGV.shift # get the sub-command
45
+ cmd = arguments.shift # get the sub-command
25
46
  case cmd
26
- when "list"
47
+ when "list", "l"
27
48
  list
28
- when "search"
29
- search
30
- when "add"
31
- add
49
+ when "peek", "p"
50
+ raise CommandError.new("No arguments given for 'peek' command.") if arguments.empty?
51
+ view(arguments)
52
+ when "search", "s"
53
+ raise CommandError.new("No arguments given for 'search' command.") if arguments.empty?
54
+ search(arguments)
55
+ when "add", "a"
56
+ raise CommandError.new("No arguments given for 'add' command.") if arguments.empty?
57
+ add(arguments)
32
58
  when "help"
33
59
  help
34
60
  else
35
- error "Unknown gemignore command '#{cmd}'."
36
- notice "Run 'gemignore help' to display usage information."
61
+ raise CommandError.new("Unknown gemignore command '#{cmd}'.")
62
+ help
37
63
  end
38
-
39
64
  end
40
65
 
66
+
41
67
  # Displays some usage information
42
68
  def help
43
- notice <<-BANNER
69
+ msg <<-BANNER
44
70
  gemignore - .gitignore snippet utility
45
71
  usage: gemignore <command> <input>
46
72
 
47
- Available commands are:
48
- list Lists all available snippets
49
- search Searches for snippets containing <input>
50
- add Add a snippet to the .gitignore file in your working directory
51
- help Display this message
73
+ Available commands are (shortcut in parentheses):
74
+ (l)ist Lists all available snippets
75
+ (p)eek Show contents of given snippets
76
+ (s)earch Searches for snippets containing <input>
77
+ (a)dd Add a snippet identified by <input> to the .gitignore file in your working directory
78
+ help Display this message
79
+
80
+ You may use the either the full command or the shortcut, e.g.:
81
+
82
+ gemignore add linux osx
83
+
84
+ is equivalent to
85
+
86
+ gemignore a linux osx
87
+
52
88
  BANNER
53
89
  end
54
90
 
91
+
55
92
  # Check if there is an case insensitive match in the fetched snippet list, in which
56
93
  # case a list containing only that snippet is returned. Otherwise, the entire list
57
94
  # of snippets is retuned unmodified.
@@ -65,40 +102,61 @@ BANNER
65
102
  end
66
103
  end
67
104
 
105
+
68
106
  # Returns the comment that is added before a gitignore snippet
69
107
  def gitignoreCommentForSnippet(snippet)
70
108
  "\n\n# Added by gemignore. Snippet '#{snippet}'\n"
71
109
  end
72
110
 
111
+
73
112
  # Displays a list of available .gitignore snippets
74
113
  def list
75
114
  msg "Available .gitignore snippets:", 1
76
- fetch().each do |f|
77
- notice f, 2
115
+ puts table(fetch())
116
+ end
117
+
118
+
119
+ # Displays the contents of the matched snippets
120
+ def view(args)
121
+ findSnippets(args) do |s|
122
+ notice "Displaying snippet '#{s}'", 2
123
+ puts fetchFile(s)
78
124
  end
79
125
  end
80
126
 
127
+
81
128
  # Searches for a given snippet name
82
- def search
83
- results = fetch(ARGV[0])
129
+ def search(args)
130
+ keyword = args.shift
131
+ results = fetch(keyword)
132
+
84
133
  if(results.length < 1)
85
- error "No snippets found for '#{ARGV[0]}'", 1
134
+ error "No snippets found for '#{keyword}'", 1
86
135
  else
87
- msg "Snippets found for '#{ARGV[0]}':", 1
88
- results.each do |f|
89
- notice f, 2
90
- end
91
-
136
+ msg "Snippets found for '#{keyword}':", 1
137
+ puts table(results)
92
138
  end
139
+
140
+ search(args) if not args.empty?
93
141
  end
94
142
 
143
+
95
144
  # Adds the snippet to the .gitignore file in the current working
96
145
  # directory in case it exists and the given snippet identifier matched
97
146
  # exactly one snippet.
98
- def add
99
- keyword = ARGV[0]
147
+ def add(args)
148
+ findSnippets(args) { |s| performAdd(s) }
149
+ end
150
+
151
+
152
+ # Searches for snippets matching the given keywords (an individual search is performed
153
+ # for every array element. The passed block is called with the name of every found
154
+ # snippet (excluding the '.gitignore' suffix)
155
+ def findSnippets(args, &block)
156
+ keyword = args.shift
100
157
  snippets = fetch(keyword)
101
158
  snippets = searchExactMatch(snippets, keyword)
159
+
102
160
  if snippets.length < 1
103
161
  error "No snippets found for '#{keyword}'", 1
104
162
  elsif snippets.length > 1
@@ -108,10 +166,13 @@ BANNER
108
166
  notice f, 2
109
167
  end
110
168
  else
111
- performAdd(snippets.first)
169
+ block.call snippets.first
112
170
  end
171
+
172
+ findSnippets(args, &block) if not args.empty?
113
173
  end
114
174
 
175
+
115
176
  # Adds the given snippet in case the .gitignore file exists.
116
177
  def performAdd(snippet)
117
178
  if not File.exists?(".gitignore")
@@ -128,6 +189,7 @@ BANNER
128
189
  end
129
190
  end
130
191
 
192
+
131
193
  # Creates a Regexp for the given string. Will be case-insensitive if the
132
194
  # input does not contain any uppercase characters. Wildcards are
133
195
  # added before and after the input, so the regex will match anything containing
@@ -139,44 +201,30 @@ BANNER
139
201
  Regexp.new("(.*#{input}.*)", opt)
140
202
  end
141
203
 
204
+
142
205
  # Fetches the list of available snippets via the GitHub API
143
- #--
144
- # FIXME: Do some (url) refactoring
145
- #++
206
+ #
146
207
  def fetch(search = nil)
147
208
  search = regexpForInput(search)
148
- data = Net::HTTP.get( URI.parse('http://github.com/api/v2/json/blob/all/github/gitignore/master') )
149
- response = JSON.parse(data)
150
209
 
151
- files = response["blobs"].map do |k,v|
152
- t = k.split('.')
210
+ files = GitHub.fileList(@snippetRepository, @snippetBranch).keys
211
+ files.map! do |f|
212
+ t = f.split('.')
153
213
  (t.pop; t.join('.') =~ search; $1) if t.last === 'gitignore'
154
214
  end
155
-
156
215
  files.compact
157
216
  end
158
217
 
218
+
159
219
  # Fetches a snippet file from GitHub
160
- #--
161
- # FIXME: Do some (url) refactoring
162
- #++
220
+ #
163
221
  def fetchFile(snippet)
164
- url = URI.parse("https://raw.github.com/github/gitignore/master/#{snippet}.gitignore")
222
+ files = GitHub.fileList(@snippetRepository, @snippetBranch)
223
+ sha = files["#{snippet}.gitignore"]
165
224
 
166
- http = Net::HTTP.new(url.host, url.port)
167
- http.use_ssl = true if url.scheme == "https" # enable SSL/TLS
225
+ raise ArgumentError.new("No gitignore snippet matching '#{snippet}' found") if sha.nil?
168
226
 
169
- data = ""
170
- http.start do
171
- http.request_get(url.path) do |res|
172
- data = res.body
173
- end
174
- end
175
-
176
- data
227
+ GitHub.getFile(@snippetRepository, sha)
177
228
  end
178
229
  end
179
-
180
-
181
-
182
230
  end
@@ -1,24 +1,58 @@
1
+ require 'terminfo'
2
+ require 'terminal-table'
3
+
1
4
  module GemIgnore
5
+
6
+ # Exceptions thrown if GemIgnore receives wrong command line arguments
7
+ #
8
+ class CommandError < ArgumentError
9
+ end
10
+
11
+
12
+ # Module to encapsulate some utility functions used within GemIgnore
13
+ #
2
14
  module Util
3
15
 
4
16
  def msg(msg, level=0)
17
+ puts (prefix(level) + msg)
18
+ end
19
+
20
+
21
+ def success(msg, level=0)
5
22
  puts (prefix(level) + msg).foreground(:green)
6
23
  end
7
24
 
25
+
8
26
  def notice(msg, level=0)
9
27
  puts (prefix(level) + msg).foreground(:yellow)
10
28
  end
11
29
 
30
+
12
31
  def error(msg, level=0)
13
32
  puts (prefix(level) + msg).foreground(:red)
14
33
  end
15
34
 
35
+
16
36
  def prefix(level)
17
37
  return "" if level <= 0
18
38
  ("-" * level) + "> "
19
39
  end
20
40
 
41
+ def table(items)
42
+ maxLength = (items.map { |e| e.length }).max
43
+
44
+ columns = TermInfo.screen_size[1]
45
+ itemsPerRow = (columns/maxLength).floor
21
46
 
47
+ itemsInRows = items.reduce([[]]) do |memo, obj|
48
+ memo.push([]) if memo.last.length >= itemsPerRow
49
+ memo.last.push(obj)
50
+ memo
51
+ end
22
52
 
53
+ table = Terminal::Table.new :rows => itemsInRows
54
+ table.style = {:border_x => "", :border_i => "", :border_y => ""}
55
+ table.to_s
56
+ end
23
57
  end
24
- end
58
+ end
@@ -1,5 +1,74 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
+ GEMIGNORE_PATH = "../bin/gemignore"
4
+
3
5
  describe "Gemignore" do
4
6
 
7
+ # Basic usage tests
8
+
9
+ it "should not throw an error when listing all snippets" do
10
+ lambda { GemIgnore::Main.new.dispatch(["l"]) }.should_not raise_error
11
+ lambda { GemIgnore::Main.new.dispatch(["list"]) }.should_not raise_error
12
+ end
13
+
14
+ it "should not throw an error when peeking into a snippet" do
15
+ lambda { GemIgnore::Main.new.dispatch(["p", "Actionscript"]) }.should_not raise_error
16
+ lambda { GemIgnore::Main.new.dispatch(["peek", "Actionscript"]) }.should_not raise_error
17
+ end
18
+
19
+ it "should not throw an error when search for a snippet" do
20
+ lambda { GemIgnore::Main.new.dispatch(["search", "lin"]) }.should_not raise_error
21
+ lambda { GemIgnore::Main.new.dispatch(["s", "lin"]) }.should_not raise_error
22
+ end
23
+
24
+ it "should be able to successfully add all snippets" do
25
+ # Change CWD to tests/ so that we don't accidentally modify another .gitignore file
26
+ Dir.chdir(File.dirname(__FILE__))
27
+
28
+ # Clear potential old .gitignore file
29
+ File.delete('.gitignore') if File.exists?('.gitignore')
30
+ File.new('.gitignore', 'w')
31
+
32
+ gemignore = GemIgnore::Main.new
33
+ snippets = gemignore.fetch('') # Get all snippets
34
+
35
+ gitignoreLines = 0 # File should be empty, we created it in #setup
36
+ gitignoreCommentLength = gemignore.gitignoreCommentForSnippet('foobar').split("\n").length
37
+
38
+ snippets.each do |snippet|
39
+ puts %x[#{GEMIGNORE_PATH} add #{snippet}]
40
+
41
+ gitignore = File.readlines('.gitignore')
42
+
43
+ # Make sure that adding the snippet did actually add something to the file
44
+ (gitignore.length >= (gitignoreLines + gitignoreCommentLength)).should be true
45
+ gitignoreLines = gitignore.length
46
+
47
+ # Asserting that there is not HTML in the added snippet, which would mean there
48
+ # was a 404 error when fetching the snippet.
49
+ gitignore.grep(/<html>/).should be_empty
50
+ end
51
+ end
52
+
53
+
54
+
55
+ # Error scenarios
56
+
57
+ it "should throw an error when a wrong subcommand is passed" do
58
+ lambda { GemIgnore::Main.new.dispatch(["foobarbaz"]) }.should raise_error(GemIgnore::CommandError)
59
+ end
60
+
61
+ it "should throw an error when no subcommand is passed" do
62
+ lambda { GemIgnore::Main.new.dispatch([]) }.should raise_error(GemIgnore::CommandError)
63
+ end
64
+
65
+
66
+
67
+ # Low - level tests
68
+
69
+ it "should fetch the file list without .gitignore extension" do
70
+ x = GemIgnore::Main.new.fetch
71
+ x.each { |i| i.split('.').last.should_not eq('gitignore') }
72
+ end
73
+
5
74
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gemignore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.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: 2011-11-06 00:00:00.000000000Z
12
+ date: 2012-05-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70346489392340 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 1.5.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70346489392340
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.5.1
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rainbow
27
- requirement: &70346489390960 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,32 +37,95 @@ dependencies:
32
37
  version: 1.1.1
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70346489390960
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.1.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: octokit
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.5
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.5
62
+ - !ruby/object:Gem::Dependency
63
+ name: terminal-table
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.4.5
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.4.5
78
+ - !ruby/object:Gem::Dependency
79
+ name: ruby-terminfo
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.1.1
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.1.1
36
94
  - !ruby/object:Gem::Dependency
37
95
  name: rspec
38
- requirement: &70346489389620 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
39
97
  none: false
40
98
  requirements:
41
99
  - - ~>
42
100
  - !ruby/object:Gem::Version
43
- version: 2.3.0
101
+ version: 2.10.0
44
102
  type: :development
45
103
  prerelease: false
46
- version_requirements: *70346489389620
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 2.10.0
47
110
  - !ruby/object:Gem::Dependency
48
111
  name: bundler
49
- requirement: &70346489388420 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
50
113
  none: false
51
114
  requirements:
52
115
  - - ~>
53
116
  - !ruby/object:Gem::Version
54
- version: 1.0.0
117
+ version: 1.1.0
55
118
  type: :development
56
119
  prerelease: false
57
- version_requirements: *70346489388420
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: 1.1.0
58
126
  - !ruby/object:Gem::Dependency
59
127
  name: jeweler
60
- requirement: &70346489387220 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
61
129
  none: false
62
130
  requirements:
63
131
  - - ~>
@@ -65,18 +133,12 @@ dependencies:
65
133
  version: 1.6.0
66
134
  type: :development
67
135
  prerelease: false
68
- version_requirements: *70346489387220
69
- - !ruby/object:Gem::Dependency
70
- name: rcov
71
- requirement: &70346489385860 !ruby/object:Gem::Requirement
136
+ version_requirements: !ruby/object:Gem::Requirement
72
137
  none: false
73
138
  requirements:
74
- - - ! '>='
139
+ - - ~>
75
140
  - !ruby/object:Gem::Version
76
- version: '0'
77
- type: :development
78
- prerelease: false
79
- version_requirements: *70346489385860
141
+ version: 1.6.0
80
142
  description: gemignore allows you to automatically insert a wide range of preset .gitignore
81
143
  snippets into your .gitignore files
82
144
  email: lucas@x3ro.de
@@ -84,26 +146,25 @@ executables:
84
146
  - gemignore
85
147
  extensions: []
86
148
  extra_rdoc_files:
87
- - LICENSE.txt
88
- - README.rdoc
149
+ - README.md
89
150
  files:
90
151
  - .document
91
152
  - .rspec
153
+ - .yardopts
92
154
  - Changelog
93
155
  - Gemfile
94
- - LICENSE.txt
95
- - README.rdoc
156
+ - README.md
96
157
  - Rakefile
97
158
  - VERSION
98
159
  - bin/.gitignore
99
160
  - bin/gemignore
100
161
  - gemignore.gemspec
101
162
  - lib/gemignore.rb
163
+ - lib/gemignore/github.rb
102
164
  - lib/gemignore/main.rb
103
165
  - lib/gemignore/util.rb
104
166
  - spec/gemignore_spec.rb
105
167
  - spec/spec_helper.rb
106
- - tests/gemignore_add_test.rb
107
168
  homepage: http://coding-journal.com/hassle-free-gitignore-management-with-gemignore/
108
169
  licenses:
109
170
  - MIT
@@ -119,7 +180,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
180
  version: '0'
120
181
  segments:
121
182
  - 0
122
- hash: 2488779062565889007
183
+ hash: -4292039963005680038
123
184
  required_rubygems_version: !ruby/object:Gem::Requirement
124
185
  none: false
125
186
  requirements:
@@ -128,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
189
  version: '0'
129
190
  requirements: []
130
191
  rubyforge_project:
131
- rubygems_version: 1.8.6
192
+ rubygems_version: 1.8.21
132
193
  signing_key:
133
194
  specification_version: 3
134
195
  summary: A command-line tool which ought to simplify your daily .gitignore hassle
@@ -1,20 +0,0 @@
1
- Copyright (c) 2011 Lucas Jenß
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.
@@ -1,27 +0,0 @@
1
- = gemignore
2
-
3
- This is a handy little tool for all people who work with Git. It allows you to easily add .gitignore snippets to the .gitignore file in your current working directory. The snippets are taken from https://github.com/github/gitignore , so if there is anything missing, feel free to fork that repository and create a pull request :)
4
-
5
- = Usage
6
-
7
- To search for a .gitignore snippet, simply type
8
-
9
- $ gemignore search searchword
10
-
11
- To list all available snippets run
12
-
13
- $ gemignore list
14
-
15
- And finally, to add a snippet to the .gitignore file in the <b>current working directory</b>:
16
-
17
- $ gemignore add Global/OSX
18
-
19
- To display usage information you can use
20
-
21
- $ gemignore help
22
-
23
- == Copyright
24
-
25
- Copyright (c) 2011 Lucas Jenß. See LICENSE.txt for
26
- further details.
27
-
@@ -1,45 +0,0 @@
1
- require 'test/unit'
2
- require 'pathname'
3
- require 'pp'
4
-
5
- lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
6
- $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
7
-
8
- require 'gemignore'
9
-
10
- GEMIGNORE_PATH = "../bin/gemignore"
11
-
12
- class GemIgnoreAddTest < Test::Unit::TestCase
13
-
14
- def test_all_snippets
15
- gemignore = GemIgnore::Main.new
16
- snippets = gemignore.fetch('') # Get all snippets
17
-
18
- gitignoreLines = 0 # File should be empty, we created it in #setup
19
- gitignoreCommentLength = gemignore.gitignoreCommentForSnippet('foobar').split("\n").length
20
-
21
- snippets.each do |snippet|
22
- puts %x[#{GEMIGNORE_PATH} add #{snippet}]
23
-
24
- gitignore = File.readlines('.gitignore')
25
-
26
- # Make sure that adding the snippet did actually add something to the file
27
- assert(gitignore.length >= (gitignoreLines + gitignoreCommentLength), "Adding Snippet #{snippet} didn't actually add anything")
28
- gitignoreLines = gitignore.length
29
-
30
- # Asserting that there is not HTML in the added snippet, which would mean there
31
- # was a 404 error when fetching the snippet.
32
- assert(gitignore.grep(/<html>/).empty?, "Adding Snippet #{snippet} failed (HTML in the .gitignore file)")
33
- end
34
- end
35
-
36
- def setup
37
- # Change CWD to tests/ so that we don't accidentally modify another .gitignore file
38
- Dir.chdir(File.dirname(__FILE__))
39
-
40
- # Clear potential old .gitignore file
41
- File.delete('.gitignore') if File.exists?('.gitignore')
42
- File.new('.gitignore', 'w')
43
- end
44
-
45
- end