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