gemignore 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/Changelog +17 -1
- data/Gemfile +5 -3
- data/README.md +40 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/gemignore +1 -1
- data/gemignore.gemspec +32 -27
- data/lib/gemignore.rb +6 -1
- data/lib/gemignore/github.rb +98 -0
- data/lib/gemignore/main.rb +109 -61
- data/lib/gemignore/util.rb +35 -1
- data/spec/gemignore_spec.rb +69 -0
- metadata +90 -29
- data/LICENSE.txt +0 -20
- data/README.rdoc +0 -27
- data/tests/gemignore_add_test.rb +0 -45
data/.yardopts
ADDED
@@ -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.
|
12
|
-
gem "bundler", "~> 1.
|
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
|
data/README.md
ADDED
@@ -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
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/bin/gemignore
CHANGED
data/gemignore.gemspec
CHANGED
@@ -4,43 +4,42 @@
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "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 = [
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
15
|
-
s.executables = [
|
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
|
-
"
|
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
|
-
"
|
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 =
|
40
|
-
s.licenses = [
|
41
|
-
s.require_paths = [
|
42
|
-
s.rubygems_version =
|
43
|
-
s.summary =
|
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.
|
52
|
-
s.
|
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<
|
59
|
-
s.add_dependency(%q<
|
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<
|
67
|
-
s.add_dependency(%q<
|
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
|
|
data/lib/gemignore.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
module GemIgnore
|
2
2
|
end
|
3
3
|
|
4
|
-
|
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
|
+
|
data/lib/gemignore/main.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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 =
|
45
|
+
cmd = arguments.shift # get the sub-command
|
25
46
|
case cmd
|
26
|
-
when "list"
|
47
|
+
when "list", "l"
|
27
48
|
list
|
28
|
-
when "
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
36
|
-
|
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
|
-
|
69
|
+
msg <<-BANNER
|
44
70
|
gemignore - .gitignore snippet utility
|
45
71
|
usage: gemignore <command> <input>
|
46
72
|
|
47
|
-
Available commands are:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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()
|
77
|
-
|
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
|
-
|
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 '#{
|
134
|
+
error "No snippets found for '#{keyword}'", 1
|
86
135
|
else
|
87
|
-
msg "Snippets found for '#{
|
88
|
-
results
|
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
|
-
|
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
|
-
|
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 =
|
152
|
-
|
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
|
-
|
222
|
+
files = GitHub.fileList(@snippetRepository, @snippetBranch)
|
223
|
+
sha = files["#{snippet}.gitignore"]
|
165
224
|
|
166
|
-
|
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
|
-
|
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
|
data/lib/gemignore/util.rb
CHANGED
@@ -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
|
data/spec/gemignore_spec.rb
CHANGED
@@ -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.
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
39
97
|
none: false
|
40
98
|
requirements:
|
41
99
|
- - ~>
|
42
100
|
- !ruby/object:Gem::Version
|
43
|
-
version: 2.
|
101
|
+
version: 2.10.0
|
44
102
|
type: :development
|
45
103
|
prerelease: false
|
46
|
-
version_requirements:
|
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:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
50
113
|
none: false
|
51
114
|
requirements:
|
52
115
|
- - ~>
|
53
116
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.
|
117
|
+
version: 1.1.0
|
55
118
|
type: :development
|
56
119
|
prerelease: false
|
57
|
-
version_requirements:
|
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:
|
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:
|
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:
|
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
|
-
-
|
88
|
-
- README.rdoc
|
149
|
+
- README.md
|
89
150
|
files:
|
90
151
|
- .document
|
91
152
|
- .rspec
|
153
|
+
- .yardopts
|
92
154
|
- Changelog
|
93
155
|
- Gemfile
|
94
|
-
-
|
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:
|
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.
|
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
|
data/LICENSE.txt
DELETED
@@ -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.
|
data/README.rdoc
DELETED
@@ -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
|
-
|
data/tests/gemignore_add_test.rb
DELETED
@@ -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
|