outsider 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +160 -0
- data/lib/outsider/outsider.rb +305 -0
- data/lib/rubygems_plugin.rb +11 -0
- metadata +66 -0
data/README.rdoc
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
==Introduction
|
2
|
+
Outsider is a rubygems plugin which allows a gem to install files outside its own directory.
|
3
|
+
|
4
|
+
===History
|
5
|
+
Outsider was born because an application I am developing needed to install icons and desktop
|
6
|
+
files in a system wide directory (such as <tt>/usr/share</tt>) to correctly integrate
|
7
|
+
with the desktop environment. Since (as far as I know) rubygems doesn't offer this
|
8
|
+
possibility, but I definitly wanted the user to install my application using a
|
9
|
+
simple <tt>gem install</tt> command, rather than using a more complicated build
|
10
|
+
system, I decided to write a general rubygems plugin allowing this.
|
11
|
+
|
12
|
+
===Features
|
13
|
+
* Allows a gem developer to specify which files should be installed system-wide,
|
14
|
+
and where exactly to install them, in a YAML file called outsider_files
|
15
|
+
placed in the top level directory of the gem
|
16
|
+
* Missing directories in the installation path are created automatically
|
17
|
+
* Allows ERB tags in the installation paths, so that they can be tailored on the
|
18
|
+
user's system
|
19
|
+
* Automatically detects whether the gem is being installed globally or in the user's
|
20
|
+
home directory. Allows to specify two different installation paths or changes
|
21
|
+
the default installation path so that files are installed in the home directory
|
22
|
+
in case of a user install
|
23
|
+
* Automatically handles uninstalls of the files when the gem is installed
|
24
|
+
* In case two gems (including multiple versions of the same gem) install a file
|
25
|
+
in the same place, automatically reinstalls the file owned by the older gem when
|
26
|
+
the newer one is installed
|
27
|
+
|
28
|
+
===Drawbacks
|
29
|
+
* To find out whether a user or a system-wide install is being performed, Outsider
|
30
|
+
checks whether the gem installation directory is a subdirectory of <tt>ENV['HOME']</tt>.
|
31
|
+
This means that things will break if you have the +GEM_HOME+ environment variable
|
32
|
+
also pointing to a subdirectory of your home directory. This should be a rare
|
33
|
+
situation, however.
|
34
|
+
* When multiple gems install a file in the same place, the gem installed last will
|
35
|
+
overwrite the file installed by the other gem, so only the last version of the
|
36
|
+
file will be availlable. This should only be an issue when having different versions
|
37
|
+
of the same gem installed (as different gems shouldn't install the same file).
|
38
|
+
This can lead to problems if an older version of the gem is loaded and if the
|
39
|
+
files installed by different versions of the gem are incompatible.
|
40
|
+
* It is only tested on linux. It should work on UNIX-like systems. As it is, I'm
|
41
|
+
almost positive it doesn't work on Windows. Most of the plugin is system-independent,
|
42
|
+
but there will be issues with default paths and user-installs.
|
43
|
+
|
44
|
+
==Usage
|
45
|
+
To have Outsider install files outside the gem directory, you need to include in
|
46
|
+
the gem sources a file called +outsider_files+ containing a YAML hash. Note that
|
47
|
+
both the +outsider_files+ and the files to install should be added to the +source+
|
48
|
+
attribute of the gem specification object.
|
49
|
+
|
50
|
+
Keys in the hash represent the paths of the files to install relative to the gem directory,
|
51
|
+
while entries can be either strings or arrays with two elements. If the entry is
|
52
|
+
an array, the first element is the installation path in case of a system-wide install,
|
53
|
+
while the second is the the path in case of a user install. In all cases, installation
|
54
|
+
paths can contain ERB templates. In the case of a user install, you can specify
|
55
|
+
the user's home directory with ~ (but only at the beginning of the file). You *can't*
|
56
|
+
use this way to specify another user's home directory, however.
|
57
|
+
|
58
|
+
In all cases, if the destination path (after all replacements have been carried out)
|
59
|
+
ends with a slash (+/+), the name of the original file (as returned by File.basename)
|
60
|
+
is appended to it.
|
61
|
+
|
62
|
+
===User installs
|
63
|
+
The following algorithm is used to determine the path to install a given file
|
64
|
+
in case of user install:
|
65
|
+
* if the entry associated with a file is an array, the second value in the array
|
66
|
+
will be used. If it's a relative path (that is, it doesn't start with +/+), then
|
67
|
+
it is assumed to be relative to the home directory. For example, if the second
|
68
|
+
entry of the array is <tt>abc/def.rb</tt>, then the file will be installed in
|
69
|
+
<tt>ENV['HOME']/abc/def.rb</tt>
|
70
|
+
* if the entry associated with the file is a string, the path it contains is considered
|
71
|
+
relative to the user's home directory (even if the path is absolute). So, if the
|
72
|
+
path is <tt>/xyz/abc.rb</tt>, it will be installed in <tt>ENV['HOME']/xyz/abc.rb</tt>.
|
73
|
+
However, often this is not what one wants. For example, a file usually installed
|
74
|
+
in <tt>/usr/local/</tt> should be installed directly in <tt>ENV['HOME']</tt>,
|
75
|
+
not in <tt>ENV['HOME']/usr/local</tt>. To avoid this, the following replacements
|
76
|
+
are performed *at the beginning of the string*:
|
77
|
+
* <tt>/bin/</tt> -> <tt>ENV['HOME']/bin</tt>
|
78
|
+
* <tt>/sbin/</tt> -> <tt>ENV['HOME']/bin</tt>
|
79
|
+
* <tt>/usr/sbin/</tt> -> <tt>ENV['HOME']/bin</tt>
|
80
|
+
* <tt>/usr/local/share/</tt> -> <tt>ENV['HOME']/.local/share</tt>
|
81
|
+
* <tt>/usr/share/</tt> -> <tt>ENV['HOME']/.local/share</tt>
|
82
|
+
* <tt>/usr/</tt> -> <tt>ENV['HOME']</tt>
|
83
|
+
* <tt>/usr/local/</tt> -> <tt>ENV['HOME']</tt>
|
84
|
+
* <tt>/var/</tt> -> <tt>ENV['HOME']</tt>
|
85
|
+
* <tt>/opt/</tt> -> <tt>ENV['HOME']</tt>
|
86
|
+
* <tt>/etc/</tt> -> <tt>ENV['HOME']</tt>
|
87
|
+
|
88
|
+
For example, if the installation path is <tt>/usr/local/share/my_dir/my_file</tt>,
|
89
|
+
in case of a user install the file will be installed in <tt>ENV['HOME']/.local/share/my_dir/my_file</tt>.
|
90
|
+
If you don't want this replacements to be performed, then you need to specify
|
91
|
+
a separate path for the user install (by using an array rather than a string
|
92
|
+
in +outsider_files+).
|
93
|
+
|
94
|
+
In all cases, all these operations are carried out *after* having expanded the
|
95
|
+
ERB templates.
|
96
|
+
|
97
|
+
===Example
|
98
|
+
|
99
|
+
This is an example +outsider_files+.
|
100
|
+
|
101
|
+
file1: /usr/share/file1
|
102
|
+
file2: "<%= `kde4-config --path apps`.strip.split(':')[-1]%/file2>"
|
103
|
+
dir/file3: [/usr/file3, "<%=File.join ENV['HOME'], 'dir', 'file3'%>"]
|
104
|
+
file4: [/etc/file4, my_dir/file4]
|
105
|
+
file5: /usr/dir/
|
106
|
+
file6: [/usr/file6, ~/test/file6]
|
107
|
+
|
108
|
+
In case of a global installation, this produces the following files (note that the
|
109
|
+
third entry depends on your system and will break if you dont't have the kde4-config
|
110
|
+
program in your PATH):
|
111
|
+
* <tt>/usr/share/file1</tt>
|
112
|
+
* <tt>/usr/share/applnk/file2</tt>
|
113
|
+
* <tt>/usr/file3</tt>
|
114
|
+
* <tt>/etc/file4</tt>
|
115
|
+
* <tt>/usr/dir/file5</tt>
|
116
|
+
* <tt>/usr/file6</tt>
|
117
|
+
|
118
|
+
In case of a user install, this is what you'd get (assuming your home directory
|
119
|
+
is <tt>/home/your_name</tt>):
|
120
|
+
* <tt>/home/your_name/.local/share/file1</tt>
|
121
|
+
* <tt>/home/your_name/applnk/file2</tt>
|
122
|
+
* <tt>/home/your_name/dir/file3</tt>
|
123
|
+
* <tt>/home/your_name/file4</tt>
|
124
|
+
* <tt>/home/your_name/file5</tt>
|
125
|
+
* <tt>/home/your_name/test/file6</tt>
|
126
|
+
|
127
|
+
=== The record file
|
128
|
+
To keep track of which files each gem has installed, Outsider uses files called
|
129
|
+
+record_files+.
|
130
|
+
|
131
|
+
A record file contains a list of files installed using Outsider, together with
|
132
|
+
the gems which installed them and the _full path_ of the original files from which
|
133
|
+
they were installed.
|
134
|
+
|
135
|
+
There are two record files, one used to keep trace of files installed during global
|
136
|
+
installations and one used for user installations. The latter is always
|
137
|
+
<tt>ENV['HOME']/.outsider/installed_files</tt>, while the former is determined
|
138
|
+
according to the following algorithm:
|
139
|
+
* if the +OUTSIDER_RECORD_FILE+ environment variable is set, the path it contains
|
140
|
+
will be used (this is mainly for testing, you shouldn't use it)
|
141
|
+
* if the +OUTSIDER_RECORD_FILE+ environment variable isn't set and the file
|
142
|
+
<tt>/etc/outsider.conf</tt> exists and contains a single filename, then that
|
143
|
+
file will be used
|
144
|
+
* otherwise the file <tt>/var/lib/outsider/installed_files</tt> will be used
|
145
|
+
|
146
|
+
If a file with the same name as the record file already exists but is not a valid
|
147
|
+
record file, a warning will be issued, the file will be renamed and a new record
|
148
|
+
file will be created.
|
149
|
+
|
150
|
+
If the record file is deleted or becomes broken, already installed files won't
|
151
|
+
be uninstalled any more. The next time you install a gem, a new record file will
|
152
|
+
be created.
|
153
|
+
|
154
|
+
==Author
|
155
|
+
Stefano Crocco (stefano.crocco@alice.it)
|
156
|
+
|
157
|
+
== License
|
158
|
+
Outsider is Copyright © 2010 Stefano Crocco.
|
159
|
+
|
160
|
+
Outside is free software and is distributed under the terms of the Ruby license
|
@@ -0,0 +1,305 @@
|
|
1
|
+
# Copyright (c) 2010 Stefano Crocco <stefano.crocco@alice.it>
|
2
|
+
# Distributed under the terms of the Ruby license
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'erb'
|
7
|
+
require 'pathname'
|
8
|
+
|
9
|
+
# Namespace for the Outsider gem
|
10
|
+
module Outsider
|
11
|
+
|
12
|
+
# Class which installs and uninstalls files
|
13
|
+
class Installer
|
14
|
+
|
15
|
+
# The path of the record file to use if the +OUTSIDER_RECORD_FILE+
|
16
|
+
# environment variable is unset
|
17
|
+
DEFAULT_RECORD_FILE = File.join '/', 'var', 'lib', 'outsider', 'installed_files'
|
18
|
+
|
19
|
+
# Exception raised when the record file is not a valid record file
|
20
|
+
class InvalidRecordFile < StandardError
|
21
|
+
|
22
|
+
# The path of the invalid record file
|
23
|
+
attr_reader :file
|
24
|
+
|
25
|
+
# Creates a new instance
|
26
|
+
#
|
27
|
+
# _file_ is the name of the invalid record file, while _msg_ is a message
|
28
|
+
# describing why the file is invalid
|
29
|
+
def initialize file, msg
|
30
|
+
@file = file
|
31
|
+
super msg + ": #{@file}"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
# Creates a new instance
|
37
|
+
#
|
38
|
+
# _dir_ is the directory where to look for the outsider_files file and the
|
39
|
+
# files to install
|
40
|
+
def initialize dir
|
41
|
+
@gem_dir = dir
|
42
|
+
@user_install = dir.start_with? ENV['HOME']
|
43
|
+
@data = begin
|
44
|
+
YAML.load File.read(File.join(dir, 'outsider_files'))
|
45
|
+
rescue SystemCallError
|
46
|
+
end
|
47
|
+
# If either the outsider_files file doesn't exist or it's empt
|
48
|
+
# (in which case YAML.load returns false), set @data to an empty hash
|
49
|
+
@data ||={}
|
50
|
+
@gem_name = File.basename(dir)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Installs the files according to the instructions in the outsider_files
|
54
|
+
# file
|
55
|
+
#
|
56
|
+
# Returns *nil*
|
57
|
+
def install_files
|
58
|
+
installed_files = []
|
59
|
+
@data.each_pair do |k, v|
|
60
|
+
dest = install_destination v
|
61
|
+
dest = File.join dest, File.basename(k) if dest.end_with? '/'
|
62
|
+
orig = File.join(@gem_dir, k)
|
63
|
+
installed_files << [orig, dest] if install_file orig, dest
|
64
|
+
end
|
65
|
+
record_installed_files installed_files unless installed_files.empty?
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
# Uninstalls the files associated with the gem in the current directory
|
70
|
+
#
|
71
|
+
# If any of those file is owned also by other gems (including by other versions
|
72
|
+
# of the same gem), then the files are only uninstalled if the gem is the last to
|
73
|
+
# have been installed. In this case, the file belonging to the previously installed
|
74
|
+
# gem is copied. If that file doesn't exist, then the one previous to it is tried,
|
75
|
+
# and so on.
|
76
|
+
#
|
77
|
+
# The record is updated to remove all mentions of the gem being uninstalled
|
78
|
+
#
|
79
|
+
# Returns *nil*
|
80
|
+
def uninstall_files
|
81
|
+
rec_file = record_file
|
82
|
+
files = begin read_record_file rec_file
|
83
|
+
rescue InvalidRecordFile then nil
|
84
|
+
end
|
85
|
+
return unless files
|
86
|
+
files.each_pair do |f, data|
|
87
|
+
gem_data = data.find{|i| i[:gem] == @gem_name}
|
88
|
+
next unless gem_data
|
89
|
+
if data.last[:gem] == @gem_name
|
90
|
+
FileUtils.rm_f f
|
91
|
+
data[0..-2].reverse_each do |d|
|
92
|
+
if File.exist? d[:origin]
|
93
|
+
FileUtils.cp d[:origin], f
|
94
|
+
break
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
data.delete gem_data
|
99
|
+
end
|
100
|
+
files.delete_if{|k, v| v.empty?}
|
101
|
+
write_record_file rec_file, files
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# The path of the record file
|
108
|
+
#
|
109
|
+
# In case of a user install, the file is always <tt>ENV['HOME']/.outsider/installed_files</tt>.
|
110
|
+
# In case of a global install, instead, the following algorithm is used:
|
111
|
+
# * if the +OUTSIDER_RECORD_FILE+ environment variable is set,
|
112
|
+
# its value is used
|
113
|
+
# * otherwise, if the file /etc/outsider.conf exists and isn't
|
114
|
+
# empty, the name of the record file is read from there
|
115
|
+
# * if all the above fails, then DEFAULT_RECORD_FILE is used
|
116
|
+
#
|
117
|
+
# Returns the name of the record file to use
|
118
|
+
def record_file
|
119
|
+
if @user_install then File.join ENV["HOME"], '.outsider', 'installed_files'
|
120
|
+
elsif ENV['OUTSIDER_RECORD_FILE'] then ENV['OUTSIDER_RECORD_FILE']
|
121
|
+
elsif File.exist?('/etc/outsider.conf')
|
122
|
+
file = File.read '/etc/outsider.conf'
|
123
|
+
file.empty? ? DEFAULT_RECORD_FILE : file
|
124
|
+
else DEFAULT_RECORD_FILE
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Creates the installation path for an entry in the +outsider_files+ file
|
129
|
+
#
|
130
|
+
# _data_ is the entry and can be a string or an array with two elements. If
|
131
|
+
# doing a global install, then the destination file is found simply by passing the
|
132
|
+
# string or the first entry of the array through ERB.
|
133
|
+
#
|
134
|
+
# In case of a user install, things are a bit more complex and change depending
|
135
|
+
# on whether _data_ is an array or a string
|
136
|
+
# * if it is an array, then the second entry will be used as path, after passing
|
137
|
+
# it through ERB. If it isn't an absolute file, it'll be considered relative
|
138
|
+
# to the user's home page.
|
139
|
+
# * if it is a string, what ERB returns will be considered a path relative to the user's
|
140
|
+
# home directory. There are a few exceptions, however. If the path starts
|
141
|
+
# with /usr/, /usr/local/, /var/, /opt/ or /etc/ then that directory will be
|
142
|
+
# replaced with the home directory. If it starts with /usr/share or /usr/local/share,
|
143
|
+
# that directory will be replaced with <tt>ENV["HOME"]/.local/share</tt>.
|
144
|
+
# If it starts with /bin/, /sbin/ or /usr/sbin/, that directory will be
|
145
|
+
# replaced by <tt>ENV["HOME"]/bin</tt>.
|
146
|
+
#
|
147
|
+
# Returns the destination path
|
148
|
+
def install_destination data
|
149
|
+
home = ENV['HOME']
|
150
|
+
if data.is_a? Array then path = data[@user_install ? 1 : 0]
|
151
|
+
else path = data
|
152
|
+
end
|
153
|
+
path = ERB.new(path).result
|
154
|
+
if @user_install and data.is_a? Array
|
155
|
+
File.expand_path path, home
|
156
|
+
elsif @user_install
|
157
|
+
replacements = [
|
158
|
+
[%r{^/bin/}, File.join(home, 'bin')],
|
159
|
+
[%r{^/sbin/}, File.join(home, 'bin')],
|
160
|
+
[%r{^/usr/sbin/}, File.join(home, 'bin')],
|
161
|
+
[%r{^/usr/local/share/}, File.join(home, '.local', 'share')],
|
162
|
+
[%r{^/usr/share/}, File.join(home, '.local', 'share')],
|
163
|
+
[%r{^/usr/local/}, home],
|
164
|
+
[%r{^/usr/}, home],
|
165
|
+
[%r[^/var/], home],
|
166
|
+
[%r[^/opt/], home],
|
167
|
+
[%r[^/etc/], home],
|
168
|
+
[%r{^~/}, home],
|
169
|
+
[%r{^(?=.)}, home]
|
170
|
+
]
|
171
|
+
match = replacements.find{|reg, _| path.match reg}
|
172
|
+
File.join match[1], path.sub(match[0], '')
|
173
|
+
else path
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Copies the file _orig_ to _dest_
|
178
|
+
#
|
179
|
+
# If the path to _dest_ doesn't exist, then the missing directories are created.
|
180
|
+
# If the file _orig_ doesn't exist, nothing is done.
|
181
|
+
#
|
182
|
+
# Returns _dest_ if the file was installed successfully and *nil* if _orig_ didn't
|
183
|
+
# exist. Raises a subclass of SystemCallError if the file couldn't be copied, for
|
184
|
+
# example due to wrong permissions
|
185
|
+
def install_file orig, dest
|
186
|
+
if File.exist? orig
|
187
|
+
begin FileUtils.cp orig, dest
|
188
|
+
rescue SystemCallError
|
189
|
+
path = Pathname.new dest
|
190
|
+
path.descend do |pth|
|
191
|
+
if pth.exist? then next
|
192
|
+
elsif pth == path
|
193
|
+
FileUtils.cp orig, dest
|
194
|
+
else FileUtils.mkdir pth.to_s
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
dest
|
199
|
+
else nil
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Adds the given files to the record file
|
204
|
+
#
|
205
|
+
# The path to the record file is given by the OUTSIDER_RECORD_FILE
|
206
|
+
# environment variable. If the variable is unset, +/var/lib/outsider/installed_files+
|
207
|
+
# is used.
|
208
|
+
#
|
209
|
+
# If the record file doesn't exist, it's created, together with any missing directory.
|
210
|
+
#
|
211
|
+
# If a file with the same name as the record file exists but it's not a valid record
|
212
|
+
# file, it will be renamed by appending a <tt>-n</tt> suffix, where _n_ is a number,
|
213
|
+
# and a new record file will be created. A warning will be issued in this case
|
214
|
+
#
|
215
|
+
# Returns *nil*
|
216
|
+
def record_installed_files files
|
217
|
+
file = record_file
|
218
|
+
begin
|
219
|
+
data = read_record_file file
|
220
|
+
data ||= {}
|
221
|
+
rescue InvalidRecordFile
|
222
|
+
data = rename_invalid_record_file file
|
223
|
+
retry
|
224
|
+
end
|
225
|
+
files.each do |f|
|
226
|
+
(data[f[1]] ||= []) << {:gem => @gem_name, :origin => File.join(@gem_dir, f[0])}
|
227
|
+
end
|
228
|
+
write_record_file file, data
|
229
|
+
nil
|
230
|
+
end
|
231
|
+
|
232
|
+
# Write data to a given record file
|
233
|
+
#
|
234
|
+
# _file_ is the name of the record file and will be created, if it doesn't exist,
|
235
|
+
# together with the directory composing its path. _data_ is the hash to write.
|
236
|
+
#
|
237
|
+
# Returns *nil*
|
238
|
+
def write_record_file file, data
|
239
|
+
record_dir = File.dirname(file)
|
240
|
+
FileUtils.mkdir_p record_dir unless File.directory? record_dir
|
241
|
+
File.open(file, 'w'){|f| YAML.dump(data, f)}
|
242
|
+
nil
|
243
|
+
end
|
244
|
+
|
245
|
+
# Reads the files installed from the given record file
|
246
|
+
#
|
247
|
+
# If the file isn't a valid record file, InvalidRecordFile is raised.
|
248
|
+
#
|
249
|
+
# _file_ is the name of the record file
|
250
|
+
#
|
251
|
+
# Returns the hash contained in the record file or *nil* if the file doesn't exist
|
252
|
+
def read_record_file file
|
253
|
+
data = begin YAML.load File.read(file)
|
254
|
+
rescue ArgumentError then raise InvalidRecordFile.new file, "Invalid YAML file"
|
255
|
+
rescue SystemCallError
|
256
|
+
return nil if !File.exist? file
|
257
|
+
raise
|
258
|
+
end
|
259
|
+
unless valid_record_contents? data
|
260
|
+
raise InvalidRecordFile.new file, "Invalid record file format"
|
261
|
+
end
|
262
|
+
data
|
263
|
+
end
|
264
|
+
|
265
|
+
# Checks whether the given object is valid content for a record file
|
266
|
+
#
|
267
|
+
# Returns *true* if _data_ is a legitimate content for a record file and *false*
|
268
|
+
# otherwise
|
269
|
+
#
|
270
|
+
# A valid record file has the following format (in YAML):
|
271
|
+
#
|
272
|
+
# /path/to/installed_file_1:
|
273
|
+
# - {:gem: name_and_version_of_gem1, :origin: path/to/original/file1}
|
274
|
+
# - {:gem: name_and_version_of_gem2, :origin: path/to/original/file2}
|
275
|
+
# /path/to/installed_file_2
|
276
|
+
# - {:gem: name_and_version_of_gem3, :origin: path/to/original/file3}
|
277
|
+
# - {:gem: name_and_version_of_gem4, :origin: path/to/original/file4}
|
278
|
+
def valid_record_contents? data
|
279
|
+
return false unless data.is_a? Hash
|
280
|
+
data.each_pair do |dest, v|
|
281
|
+
return false unless dest.is_a? String and v.is_a? Array
|
282
|
+
v.each do |gem|
|
283
|
+
return false unless gem.is_a? Hash
|
284
|
+
return false unless gem[:gem].is_a? String and gem[:origin].is_a? String
|
285
|
+
end
|
286
|
+
end
|
287
|
+
true
|
288
|
+
end
|
289
|
+
|
290
|
+
# Renames the invalid record file _file_ giving it a new unique name and issues a
|
291
|
+
# warning
|
292
|
+
#
|
293
|
+
# Returns *nil*
|
294
|
+
def rename_invalid_record_file file
|
295
|
+
n = 1
|
296
|
+
n+=1 while File.exist?( file + "-#{n}")
|
297
|
+
new_file = file + "-#{n}"
|
298
|
+
warn "The file #{file} isn't a valid record file and will be moved to #{new_file}"
|
299
|
+
FileUtils.mv file, new_file
|
300
|
+
nil
|
301
|
+
end
|
302
|
+
|
303
|
+
end
|
304
|
+
|
305
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'outsider','outsider')
|
2
|
+
|
3
|
+
Gem.post_install do |inst|
|
4
|
+
global = Outsider::Installer.new inst.spec.full_gem_path
|
5
|
+
global.install_files
|
6
|
+
end
|
7
|
+
|
8
|
+
Gem.pre_uninstall do |uninst|
|
9
|
+
global = Outsider::Installer.new uninst.spec.full_gem_path
|
10
|
+
global.uninstall_files
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: outsider
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Stefano Crocco
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-10-04 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email: stefano.crocco@alice.it
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/rubygems_plugin.rb
|
31
|
+
- lib/outsider/outsider.rb
|
32
|
+
- README.rdoc
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/stcrocco/outsider
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
segments:
|
48
|
+
- 0
|
49
|
+
version: "0"
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.3.7
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: rubygems plugin to allow a gem to install files outside its own directory
|
65
|
+
test_files: []
|
66
|
+
|