gift 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gift/recipients.yml +29 -0
- data/.gitignore +18 -0
- data/README.textile +25 -0
- data/Rakefile +17 -0
- data/VERSION +1 -0
- data/bin/gift +40 -0
- data/gift.gemspec +53 -0
- data/lib/cli.rb +175 -0
- data/lib/recipient.rb +157 -0
- metadata +97 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
--- !ruby/object:Gift::Recipient
|
2
|
+
connection: !ruby/object:Net::FTP
|
3
|
+
binary: true
|
4
|
+
debug_mode: false
|
5
|
+
last_response: |
|
6
|
+
226-Options: -a
|
7
|
+
226 3 matches total
|
8
|
+
|
9
|
+
last_response_code: "226"
|
10
|
+
mon_count: 0
|
11
|
+
mon_entering_queue: []
|
12
|
+
|
13
|
+
mon_owner:
|
14
|
+
mon_waiting_queue: []
|
15
|
+
|
16
|
+
passive: false
|
17
|
+
resume: false
|
18
|
+
sock: !ruby/object:TCPSocket {}
|
19
|
+
|
20
|
+
welcome: |
|
21
|
+
230-User dev+involved.com.au has group access to: involved
|
22
|
+
230 OK. Current restricted directory is /
|
23
|
+
|
24
|
+
host: involved.com.au
|
25
|
+
id: ftp-1
|
26
|
+
password: d8u2gy
|
27
|
+
path: gift-test
|
28
|
+
port: 21
|
29
|
+
username: dev+involved.com.au
|
data/.gitignore
ADDED
data/README.textile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
h1. Gift - Git and FTP, the easy way
|
2
|
+
|
3
|
+
"We":http://www.involved.com.au recently adopted Ruby on Rails as our primary web application framework of choice. The marriage of Rails, Git and Heroku made for a carefree development, deployment and management strategy. Unfortunately, the reality is that we're not always able to use our favourite technologies. And more often than not often a client will have existing hosting arrangements that simply cannot (easily) support a Rails setup, or maybe we're just doing a simple Wordpress blog. Regardless - we wanted to have that same ease of deployment; a way to manage development in the style to which we have become accustomed.
|
4
|
+
|
5
|
+
So we made Gift.
|
6
|
+
|
7
|
+
h2. Usage
|
8
|
+
|
9
|
+
Install the gem:
|
10
|
+
|
11
|
+
<pre>
|
12
|
+
gem install gift
|
13
|
+
</pre>
|
14
|
+
|
15
|
+
Initialise your FTP server:
|
16
|
+
|
17
|
+
<pre>
|
18
|
+
gift wrap ftp://username:password@127.0.0.1:21
|
19
|
+
</pre>
|
20
|
+
|
21
|
+
Push your commits:
|
22
|
+
|
23
|
+
<pre>
|
24
|
+
gift deliver
|
25
|
+
</pre>
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = "gift"
|
5
|
+
gemspec.summary = "Git and FTP, the easy way."
|
6
|
+
gemspec.description = "Gift provides a simple interface for pushing your site to a server that does not support git, via FTP."
|
7
|
+
gemspec.email = "nicholas@bruning.com.au"
|
8
|
+
gemspec.homepage = "http://github.com/thetron/gift"
|
9
|
+
gemspec.authors = ["Nicholas Bruning"]
|
10
|
+
gemspec.add_dependency('ptools', '>= 1.1.8')
|
11
|
+
gemspec.add_dependency('git', '>= 1.2.5')
|
12
|
+
gemspec.executables = ["gift"]
|
13
|
+
end
|
14
|
+
Jeweler::GemcutterTasks.new
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
17
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.5
|
data/bin/gift
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# == About
|
4
|
+
# Gift – Git and FTP, the easy way
|
5
|
+
# Gift provides a simple interface for pushing your site to a server that does not support git, via FTP.
|
6
|
+
#
|
7
|
+
# This version of Gift currenly only supports the master branch of a git repository.
|
8
|
+
#
|
9
|
+
# == Examples
|
10
|
+
# Start my initialising your FTP settings
|
11
|
+
# $ gift wrap ftp://username:password@127.0.0.1:21
|
12
|
+
#
|
13
|
+
# When you're ready to deploy, use:
|
14
|
+
# $ gift deliver
|
15
|
+
#
|
16
|
+
# == Usage
|
17
|
+
# $ gift wrap [server-name] ftp://username:password@127.0.0.1:21
|
18
|
+
# $ gift deliver [options]
|
19
|
+
#
|
20
|
+
# For help use: gift -h
|
21
|
+
#
|
22
|
+
# == Options
|
23
|
+
# -h, --help Displays help message
|
24
|
+
# -v, --version Display the version, then exit
|
25
|
+
# -q, --quiet Output as little as possible, overrides verbose
|
26
|
+
# -V, --verbose Verbose output
|
27
|
+
#
|
28
|
+
# == Author
|
29
|
+
# Nicholas Bruning
|
30
|
+
#
|
31
|
+
# == Copyright
|
32
|
+
# Copyright (c) 2010 Nicholas Bruning. Licensed under the MIT License:
|
33
|
+
# http://www.opensource.org/licenses/mit-license.php
|
34
|
+
|
35
|
+
# use this for testing:
|
36
|
+
# ruby lib/cli.rb wrap ftp://dev+involved.com.au:d8u2gy@involved.com.au:21/gift-test
|
37
|
+
|
38
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
39
|
+
require 'cli'
|
40
|
+
exit Gift::Cli.new(ARGV, STDIN).run
|
data/gift.gemspec
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{gift}
|
8
|
+
s.version = "0.0.5"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Nicholas Bruning"]
|
12
|
+
s.date = %q{2010-03-18}
|
13
|
+
s.default_executable = %q{gift}
|
14
|
+
s.description = %q{Gift provides a simple interface for pushing your site to a server that does not support git, via FTP.}
|
15
|
+
s.email = %q{nicholas@bruning.com.au}
|
16
|
+
s.executables = ["gift"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"README.textile"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".gift/recipients.yml",
|
22
|
+
".gitignore",
|
23
|
+
"README.textile",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"bin/gift",
|
27
|
+
"gift.gemspec",
|
28
|
+
"lib/cli.rb",
|
29
|
+
"lib/recipient.rb"
|
30
|
+
]
|
31
|
+
s.homepage = %q{http://github.com/thetron/gift}
|
32
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = %q{1.3.6}
|
35
|
+
s.summary = %q{Git and FTP, the easy way.}
|
36
|
+
|
37
|
+
if s.respond_to? :specification_version then
|
38
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
39
|
+
s.specification_version = 3
|
40
|
+
|
41
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
42
|
+
s.add_runtime_dependency(%q<ptools>, [">= 1.1.8"])
|
43
|
+
s.add_runtime_dependency(%q<git>, [">= 1.2.5"])
|
44
|
+
else
|
45
|
+
s.add_dependency(%q<ptools>, [">= 1.1.8"])
|
46
|
+
s.add_dependency(%q<git>, [">= 1.2.5"])
|
47
|
+
end
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<ptools>, [">= 1.1.8"])
|
50
|
+
s.add_dependency(%q<git>, [">= 1.2.5"])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
data/lib/cli.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'rdoc/usage'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'date'
|
7
|
+
require 'uri'
|
8
|
+
require 'net/ftp'
|
9
|
+
require 'yaml'
|
10
|
+
require 'recipient'
|
11
|
+
|
12
|
+
module Gift
|
13
|
+
class Cli
|
14
|
+
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
def initialize(arguments, stdin)
|
18
|
+
@arguments = arguments
|
19
|
+
@stdin = stdin
|
20
|
+
|
21
|
+
# Set defaults
|
22
|
+
@options = OpenStruct.new
|
23
|
+
@options.verbose = false
|
24
|
+
@options.quiet = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
if parsed_options?
|
29
|
+
puts "Start at #{DateTime.now}\n\n" if @options.verbose
|
30
|
+
|
31
|
+
output_options if @options.verbose # [Optional]
|
32
|
+
|
33
|
+
process_arguments
|
34
|
+
process_command
|
35
|
+
|
36
|
+
puts "\nFinished at #{DateTime.now}" if @options.verbose
|
37
|
+
else
|
38
|
+
output_usage
|
39
|
+
end
|
40
|
+
|
41
|
+
return 0
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def wrap
|
47
|
+
puts "Gift wrapping #{@server_address}"
|
48
|
+
|
49
|
+
#check a local git repository exists
|
50
|
+
@errors = fail(["No local git repository found"]) unless File.exists?(".git")
|
51
|
+
|
52
|
+
uri = URI.parse(@options.server_address)
|
53
|
+
recipient = Gift::Recipient.new
|
54
|
+
|
55
|
+
#recipient.id = @options.server_name
|
56
|
+
recipient.id = "ftp-1"
|
57
|
+
recipient.username = uri.userinfo.split(":")[0]
|
58
|
+
recipient.password = uri.userinfo.split(":")[1]
|
59
|
+
recipient.host = uri.host
|
60
|
+
recipient.port = uri.port
|
61
|
+
recipient.path = uri.path
|
62
|
+
|
63
|
+
begin
|
64
|
+
puts "Connected to #{recipient.host}" if recipient.valid_connection?
|
65
|
+
|
66
|
+
puts "Initialising remote files in #{recipient.host}/#{recipient.path}"
|
67
|
+
recipient.setup_remote_dirs
|
68
|
+
puts "Remote setup complete"
|
69
|
+
|
70
|
+
puts "Initialising local files"
|
71
|
+
recipient.setup_local_dirs
|
72
|
+
recipient.save
|
73
|
+
puts "Local setup complete"
|
74
|
+
rescue Exception => e
|
75
|
+
fail(["#{e} #{e.class}"])
|
76
|
+
end
|
77
|
+
|
78
|
+
#populate or refresh .gift/remotes.yml locally
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
def unwrap
|
83
|
+
#remove @server_name from local list
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def deliver
|
88
|
+
recipient = Recipient.find_by_id(nil)
|
89
|
+
puts "Delivering gift to '#{recipient.id}'"
|
90
|
+
recipient.update_remote
|
91
|
+
end
|
92
|
+
|
93
|
+
def output_version
|
94
|
+
File.open(File.join(File.dirname(__FILE__), '..', 'VERSION'), "r") do |f|
|
95
|
+
f.each { |f| puts "Gift v#{f}" }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def output_help
|
100
|
+
output_version
|
101
|
+
RDoc::usage() #exits app
|
102
|
+
end
|
103
|
+
|
104
|
+
def output_usage()
|
105
|
+
RDoc::usage('usage') # gets usage from comments above
|
106
|
+
end
|
107
|
+
|
108
|
+
def fail(errors)
|
109
|
+
puts "The following errors occurred:"
|
110
|
+
puts "\t" + errors.join("\n\t") + "\t"
|
111
|
+
output_usage
|
112
|
+
|
113
|
+
exit 0;
|
114
|
+
end
|
115
|
+
|
116
|
+
def parsed_options?
|
117
|
+
# Specify options
|
118
|
+
opts = OptionParser.new
|
119
|
+
|
120
|
+
opts.on('-h', '--help') { output_help }
|
121
|
+
opts.on('-V', '--verbose') { @options.verbose = true }
|
122
|
+
opts.on('-q', '--quiet') { @options.quiet = true }
|
123
|
+
|
124
|
+
opts.on('-v', '--version') do |version|
|
125
|
+
output_version
|
126
|
+
exit 0
|
127
|
+
end
|
128
|
+
|
129
|
+
opts.parse!(@arguments) rescue return false
|
130
|
+
|
131
|
+
process_options
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
135
|
+
def process_options
|
136
|
+
@options.verbose = false if @options.quiet
|
137
|
+
end
|
138
|
+
|
139
|
+
def output_options
|
140
|
+
puts "Options:\n"
|
141
|
+
|
142
|
+
@options.marshal_dump.each do |name, val|
|
143
|
+
puts " #{name} = #{val}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def arguments_valid?
|
148
|
+
if @command == :wrap
|
149
|
+
@options.server_address != nil
|
150
|
+
else
|
151
|
+
true
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def process_arguments
|
156
|
+
@command = (@arguments.shift || 'help').to_sym
|
157
|
+
|
158
|
+
if(@command == :wrap)
|
159
|
+
@options.server_name = @arguments.shift if @arguments.length > 1
|
160
|
+
@options.server_address = @arguments.shift
|
161
|
+
elsif( [:unwrap, :delivery].include?(@command) )
|
162
|
+
@options.server_name = @arguments.shift
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def process_command
|
167
|
+
if[:wrap, :unwrap, :deliver].include?(@command) && arguments_valid?
|
168
|
+
send(@command)
|
169
|
+
else
|
170
|
+
output_help
|
171
|
+
exit 0
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
data/lib/recipient.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'ftools'
|
2
|
+
require 'yaml'
|
3
|
+
require 'ptools'
|
4
|
+
require 'git'
|
5
|
+
|
6
|
+
module Gift
|
7
|
+
class Recipient
|
8
|
+
attr_accessor :id, :username, :password, :host, :port, :path
|
9
|
+
|
10
|
+
def valid_connection?
|
11
|
+
begin
|
12
|
+
connect
|
13
|
+
disconnect
|
14
|
+
true
|
15
|
+
rescue Exception => e
|
16
|
+
false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup_remote_dirs
|
21
|
+
connect
|
22
|
+
unless @connection.nlst.include?('.gift')
|
23
|
+
@connection.mkdir('.gift')
|
24
|
+
else
|
25
|
+
puts 'Remote gift directory already exists'
|
26
|
+
end
|
27
|
+
|
28
|
+
@connection.chdir('.gift')
|
29
|
+
|
30
|
+
unless @connection.nlst.include?('deliveries')
|
31
|
+
@connection.mkdir('deliveries')
|
32
|
+
else
|
33
|
+
puts 'Remote deliveries directory already exists'
|
34
|
+
end
|
35
|
+
disconnect
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup_local_dirs
|
39
|
+
File.makedirs '.gift' unless File.exists?('.gift')
|
40
|
+
File.makedirs '.gift/deliveries' unless File.exists?('.gift/deliveries')
|
41
|
+
File.makedirs ".gift/deliveries/#{self.id}"# unless File.exists?(".gift/deliveries/#{self.id}")
|
42
|
+
end
|
43
|
+
|
44
|
+
def update_remote
|
45
|
+
repo = Git.open('./')
|
46
|
+
|
47
|
+
remote_commit = last_remote_commit
|
48
|
+
remote_commit = repo.log.to_a.last.sha if remote_commit == ""
|
49
|
+
|
50
|
+
file_count = 0
|
51
|
+
|
52
|
+
puts("Last remote commit: #{remote_commit} | Current local commit: #{repo.log.to_a.first.sha}")
|
53
|
+
|
54
|
+
connect
|
55
|
+
repo.diff(remote_commit, repo.log.to_a.first.sha).each do |file|
|
56
|
+
unless(file.path.split('/').first == ".gift")
|
57
|
+
if file.type == "deleted"
|
58
|
+
begin
|
59
|
+
size = @connection.size(file.path)
|
60
|
+
puts "Deleting #{file.path} [ ] 0%"
|
61
|
+
delete_remote_file(file.path)
|
62
|
+
rescue Exception => e
|
63
|
+
puts "Delete skipped #{file.path} (file not found)"
|
64
|
+
end
|
65
|
+
else
|
66
|
+
puts "Uploading #{file.path} [ ] 0%"
|
67
|
+
upload_file(file.path)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
file_count += 1
|
71
|
+
end
|
72
|
+
disconnect
|
73
|
+
|
74
|
+
if file_count == 0
|
75
|
+
puts "Everything up to date!"
|
76
|
+
else
|
77
|
+
save_commit(repo.log.to_a.first.sha)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def last_remote_commit
|
82
|
+
sha = ""
|
83
|
+
connect
|
84
|
+
@connection.chdir('.gift/deliveries')
|
85
|
+
if @connection.nlst.length > 2
|
86
|
+
@connection.gettextfile(@connection.nlst.last) do |f|
|
87
|
+
sha = f
|
88
|
+
end
|
89
|
+
end
|
90
|
+
disconnect
|
91
|
+
|
92
|
+
sha
|
93
|
+
end
|
94
|
+
|
95
|
+
def save_commit(sha)
|
96
|
+
file_name = ".gift/deliveries/#{id}/#{Time.now.to_i.to_s}"
|
97
|
+
fp = File.open(file_name, "w")
|
98
|
+
fp.puts sha
|
99
|
+
fp.close
|
100
|
+
|
101
|
+
connect
|
102
|
+
@connection.chdir('.gift/deliveries')
|
103
|
+
@connection.puttextfile(file_name)
|
104
|
+
disconnect
|
105
|
+
|
106
|
+
puts "Remote state saved"
|
107
|
+
end
|
108
|
+
|
109
|
+
def save
|
110
|
+
unless self.id
|
111
|
+
self.id = "ftp-1"
|
112
|
+
end
|
113
|
+
|
114
|
+
yaml = YAML::dump(self)
|
115
|
+
fp = open('.gift/recipients.yml', 'w')
|
116
|
+
fp.write(yaml)
|
117
|
+
fp.close
|
118
|
+
end
|
119
|
+
|
120
|
+
def connect
|
121
|
+
@connection = Net::FTP.new(host, username, password)
|
122
|
+
@connection.chdir(path)
|
123
|
+
end
|
124
|
+
|
125
|
+
def disconnect
|
126
|
+
@connection.close
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.find_by_id(id)
|
130
|
+
#search recipients.yml for id
|
131
|
+
YAML::load_file('.gift/recipients.yml')
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.all
|
135
|
+
YAML::load_file('.gift/recipients.yml')
|
136
|
+
end
|
137
|
+
|
138
|
+
protected
|
139
|
+
|
140
|
+
def upload_file(filename)
|
141
|
+
#this will also have to create any missing dirs (unless they're handled the same as files)
|
142
|
+
connect
|
143
|
+
if File.binary?(filename)
|
144
|
+
@connection.putbinaryfile(filename)
|
145
|
+
else
|
146
|
+
@connection.puttextfile(filename)
|
147
|
+
end
|
148
|
+
disconnect
|
149
|
+
end
|
150
|
+
|
151
|
+
def delete_remote_file(filename)
|
152
|
+
connect
|
153
|
+
@connection.delete(filename)
|
154
|
+
disconnect
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gift
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
version: 0.0.5
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Nicholas Bruning
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-18 00:00:00 +11:00
|
18
|
+
default_executable: gift
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: ptools
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 1
|
30
|
+
- 8
|
31
|
+
version: 1.1.8
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: git
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 1
|
43
|
+
- 2
|
44
|
+
- 5
|
45
|
+
version: 1.2.5
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
description: Gift provides a simple interface for pushing your site to a server that does not support git, via FTP.
|
49
|
+
email: nicholas@bruning.com.au
|
50
|
+
executables:
|
51
|
+
- gift
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
extra_rdoc_files:
|
55
|
+
- README.textile
|
56
|
+
files:
|
57
|
+
- .gift/recipients.yml
|
58
|
+
- .gitignore
|
59
|
+
- README.textile
|
60
|
+
- Rakefile
|
61
|
+
- VERSION
|
62
|
+
- bin/gift
|
63
|
+
- gift.gemspec
|
64
|
+
- lib/cli.rb
|
65
|
+
- lib/recipient.rb
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://github.com/thetron/gift
|
68
|
+
licenses: []
|
69
|
+
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options:
|
72
|
+
- --charset=UTF-8
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
requirements: []
|
90
|
+
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.3.6
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: Git and FTP, the easy way.
|
96
|
+
test_files: []
|
97
|
+
|