sundae 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/README.rdoc +45 -25
- data/lib/sundae.rb +108 -67
- data/test/test_sundae.rb +53 -57
- data/unison/common +17 -0
- data/unison/mt_example.prf +12 -0
- data/version.txt +1 -1
- metadata +16 -10
data/.gitignore
ADDED
data/README.rdoc
CHANGED
@@ -38,6 +38,10 @@ works. Like this:
|
|
38
38
|
~> ls
|
39
39
|
bin Desktop doc etc lib local mnt share src tmp var WualaDrive
|
40
40
|
|
41
|
+
And that's it. When called, Sundae creates links so that you can
|
42
|
+
work on your files from seperate parts of life as if they were side
|
43
|
+
by side.
|
44
|
+
|
41
45
|
== Install
|
42
46
|
|
43
47
|
sudo gem install sundae
|
@@ -66,16 +70,22 @@ this:
|
|
66
70
|
`-- collection2/
|
67
71
|
` ...
|
68
72
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
+
Sundae will act on all of the <em>mnt</em>s--subdirectories of the
|
74
|
+
<em>collection</em>s, that is, the sub-subdirectories of the
|
75
|
+
<em>path</em>. The "collections" are only there to facilitate
|
76
|
+
grouping common files and syncronizing them between computers.
|
73
77
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
78
|
+
By default, all of the contents in each of the <em>mnt</em>s are
|
79
|
+
placed in the user's home directory. This can be altered by creating
|
80
|
+
a file called <tt>.sundae_path</tt> in the top of the <em>mnt</em>;
|
81
|
+
the file should contain one line, which is the absolute path to where
|
82
|
+
that directory should be "mounted."
|
83
|
+
|
84
|
+
There's one exception to the "by default everything is placed in the
|
85
|
+
home directory" rule. If the mnt directory starts with "dot-" or
|
86
|
+
"dot_" then it is placed in the dot folder formed using the rest of
|
87
|
+
the name. For example, the files in a "dot-ssh" mnt are placed in
|
88
|
+
"~/.ssh" by default.
|
79
89
|
|
80
90
|
For example, the hierarchy in my <em>path</em>s looks sort of like this:
|
81
91
|
|
@@ -86,13 +96,13 @@ For example, the hierarchy in my <em>path</em>s looks sort of like this:
|
|
86
96
|
| | |-- etc/ (~/etc will point here)
|
87
97
|
| | ` ...
|
88
98
|
| |-- dot-unison
|
89
|
-
| | |-- .sundae_path (says "~/.unison")
|
99
|
+
| | |-- .sundae_path (says "~/.unison", but not required)
|
90
100
|
| | |-- default.prf (~/.unison/default.prf will point here)
|
91
101
|
| | `
|
92
102
|
| |
|
93
103
|
|-- osx/
|
94
|
-
| |-- home_library/
|
95
|
-
| | |-- .sundae_path
|
104
|
+
| |-- home_library/
|
105
|
+
| | |-- .sundae_path (says "~/Library", required)
|
96
106
|
| | `-- Library-Keyboard_Layouts/
|
97
107
|
| | `-- Keyboard Layouts/
|
98
108
|
| | ` Colemak.keylayout
|
@@ -112,20 +122,30 @@ For example, the hierarchy in my <em>path</em>s looks sort of like this:
|
|
112
122
|
| ` ...
|
113
123
|
` ...
|
114
124
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
By default, all of the contents in each of the <em>mnt</em>s are
|
121
|
-
placed in the user's home directory. This can be altered by
|
122
|
-
creating a file called <tt>.sundae_path</tt> in the top of the
|
123
|
-
<em>mnt</em>; the file should contain one line, which is the
|
124
|
-
absolute path to where that directory should be "mounted."
|
125
|
+
Why is this double layer "collection" stuff going on? Because while
|
126
|
+
most of the time you can share a whole folder between computers,
|
127
|
+
sometimes you want to mix your config files into a folder that also
|
128
|
+
contains nonsymlinked files.
|
125
129
|
|
126
|
-
|
127
|
-
|
128
|
-
|
130
|
+
For example, your ~/.ssh folder probably has a public and private key
|
131
|
+
that you want to stay unique to that machine, but you might want to
|
132
|
+
mix in a "config" file that has host aliases that you share between
|
133
|
+
machines. You can put the file in "~/mnt/nix/.ssh/config" in the
|
134
|
+
above example, and it will get created alongside the other static
|
135
|
+
files in the "~/.ssh/" directory.
|
136
|
+
|
137
|
+
However, every time you run sundae it will check the target locations
|
138
|
+
of each file and directory (recursively) in every mnt directory for
|
139
|
+
dangling symlinks and other stuff that sundae might have created. If
|
140
|
+
you put the the file in "~/mnt/nix/dot-ssh/config", it will be placed
|
141
|
+
in the correct place and only "config" will be checked when sundae is
|
142
|
+
run (not all of the other files in "~/.ssh/").
|
143
|
+
|
144
|
+
It obviously doesn't make much of a speed difference in this case, but
|
145
|
+
if you're mixing in one file into "~/a/b/c/d/file", and there are lots
|
146
|
+
of files beneath "~/a/", then you don't want sundae to look through
|
147
|
+
everything every time it runs. Just put it in a mnt directory with a
|
148
|
+
<tt>.sundae_path</tt> of "~/a/b/c/d".
|
129
149
|
|
130
150
|
== Author
|
131
151
|
<don@ohspite.net>
|
data/lib/sundae.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'configatron'
|
3
3
|
require 'fileutils'
|
4
4
|
require 'find'
|
5
|
+
require 'pathname'
|
5
6
|
|
6
7
|
# A collection of methods to mix the contents of several directories
|
7
8
|
# together using symbolic links.
|
@@ -13,20 +14,21 @@ module Sundae
|
|
13
14
|
# :startdoc:
|
14
15
|
VERSION = ::File.read(PATH + 'version.txt').strip
|
15
16
|
|
16
|
-
DEFAULT_CONFIG_FILE =
|
17
|
+
DEFAULT_CONFIG_FILE = (Pathname.new(Dir.home) + '.sundae').expand_path
|
17
18
|
|
18
19
|
@config_file = DEFAULT_CONFIG_FILE
|
19
20
|
|
20
21
|
# Read configuration from <tt>.sundae</tt>.
|
21
22
|
#
|
22
23
|
def self.load_config_file(config_file = DEFAULT_CONFIG_FILE)
|
23
|
-
config_file ||= DEFAULT_CONFIG_FILE
|
24
|
-
config_file =
|
24
|
+
config_file ||= DEFAULT_CONFIG_FILE # if nil is passed
|
25
|
+
config_file = Pathname.new(config_file).expand_path
|
26
|
+
config_file += '.sundae' if config_file.directory?
|
25
27
|
|
26
|
-
create_template_config_file(config_file) unless
|
28
|
+
create_template_config_file(config_file) unless config_file.file?
|
27
29
|
|
28
30
|
load(config_file)
|
29
|
-
configatron.paths.map! { |p|
|
31
|
+
configatron.paths.map! { |p| Pathname.new(p).expand_path }
|
30
32
|
|
31
33
|
# An array which lists the directories where mnts are stored.
|
32
34
|
@paths = configatron.paths
|
@@ -39,13 +41,14 @@ module Sundae
|
|
39
41
|
# asking the user.
|
40
42
|
#
|
41
43
|
def self.create_template_config_file(config_file)
|
44
|
+
config_file = Pathname.new(config_file).expand_path
|
42
45
|
loop do
|
43
46
|
print "#{config_file} does not exist. Create template there? (y/n): "
|
44
47
|
ans = gets.downcase.strip
|
45
48
|
if ans == "y" || ans == "yes"
|
46
49
|
File.open(config_file, "w") do |f|
|
47
50
|
f.puts <<-EOM.gsub(/^ {14}/, '')
|
48
|
-
# -*-Ruby-*-
|
51
|
+
# -*-Ruby-*-
|
49
52
|
|
50
53
|
# An array which lists the directories where mnts are stored.
|
51
54
|
configatron.paths = ["~/mnt"]
|
@@ -76,13 +79,15 @@ module Sundae
|
|
76
79
|
# ignored (i.e., no link will be made pointing to it).
|
77
80
|
#
|
78
81
|
def self.ignore_file?(file) # :doc:
|
79
|
-
|
80
|
-
|
82
|
+
file = Pathname.new(file)
|
83
|
+
basename = file.basename.to_s
|
84
|
+
return true if basename =~ /^\.\.?$/
|
85
|
+
return true if basename == ".sundae_path"
|
81
86
|
@ignore_rules.each do |r|
|
82
87
|
if r.kind_of? Regexp
|
83
|
-
return true if
|
88
|
+
return true if basename =~ r
|
84
89
|
else
|
85
|
-
return true if
|
90
|
+
return true if file.fnmatch(r)
|
86
91
|
end
|
87
92
|
end
|
88
93
|
return false
|
@@ -92,12 +97,19 @@ module Sundae
|
|
92
97
|
# where in the file system links should be created for this mnt.
|
93
98
|
#
|
94
99
|
def self.install_location(mnt)
|
95
|
-
|
96
|
-
|
97
|
-
|
100
|
+
mnt = Pathname.new(mnt).expand_path
|
101
|
+
mnt_config = mnt + '.sundae_path'
|
102
|
+
if mnt_config.exist?
|
103
|
+
return Pathname.new(mnt_config.readlines[0].strip).expand_path
|
98
104
|
end
|
99
105
|
|
100
|
-
|
106
|
+
base = mnt.basename.to_s
|
107
|
+
match = (/dot[-_](.*)/).match(base)
|
108
|
+
if match
|
109
|
+
return Pathname.new(Dir.home) + ('.' + match[1])
|
110
|
+
end
|
111
|
+
|
112
|
+
return Pathname.new(Dir.home)
|
101
113
|
end
|
102
114
|
|
103
115
|
# Return an array of all paths in the file system where links will
|
@@ -111,11 +123,12 @@ module Sundae
|
|
111
123
|
# as an array.
|
112
124
|
#
|
113
125
|
def self.mnts_in_path(path)
|
126
|
+
Pathname.new(path).expand_path
|
114
127
|
mnts = []
|
115
|
-
collections =
|
128
|
+
collections = path.children(false).delete_if {|c| c.to_s =~ /^\./}
|
116
129
|
collections.each do |c|
|
117
|
-
collection_mnts =
|
118
|
-
collection_mnts.map! { |mnt|
|
130
|
+
collection_mnts = (path + c).children(false).delete_if {|c| c.to_s =~ /^\./}
|
131
|
+
collection_mnts.map! { |mnt| (c + mnt) }
|
119
132
|
mnts |= collection_mnts # |= is the union
|
120
133
|
end
|
121
134
|
|
@@ -128,87 +141,109 @@ module Sundae
|
|
128
141
|
mnts = []
|
129
142
|
|
130
143
|
@paths.each do |path|
|
131
|
-
next unless
|
132
|
-
mnts |= mnts_in_path(path).map { |mnt|
|
144
|
+
next unless path.exist?
|
145
|
+
mnts |= mnts_in_path(path).map { |mnt| path + mnt } # |= is the union operator
|
133
146
|
end
|
134
|
-
|
135
147
|
return mnts
|
136
148
|
end
|
137
149
|
|
138
|
-
# Return all subdirectories
|
139
|
-
# are the 'mirror' directories that are
|
150
|
+
# Return all subdirectories and files in the mnts returned by
|
151
|
+
# all_mnts. These are the 'mirror' files and directories that are
|
152
|
+
# generated by sundae.
|
140
153
|
#
|
141
|
-
def self.
|
154
|
+
def self.generated_files
|
142
155
|
dirs = Array.new
|
143
156
|
|
144
157
|
all_mnts.each do |mnt|
|
145
|
-
mnt_dirs =
|
158
|
+
mnt_dirs = mnt.children(false).delete_if { |e| ignore_file?(e) }
|
146
159
|
mnt_dirs.each do |dir|
|
147
|
-
dirs <<
|
160
|
+
dirs << (install_location(mnt) + dir)
|
148
161
|
end
|
149
162
|
end
|
150
163
|
|
151
|
-
return dirs.sort.uniq
|
164
|
+
return dirs.sort.uniq#.select { |d| d.directory? }
|
165
|
+
end
|
166
|
+
|
167
|
+
# Return all subdirectories of the mnts returned by all_mnts. These
|
168
|
+
# are the 'mirror' directories that are generated by sundae.
|
169
|
+
#
|
170
|
+
def self.generated_directories
|
171
|
+
generated_files.select {|f| f.directory?}
|
152
172
|
end
|
153
173
|
|
154
174
|
# Check for symlinks in the base directories that are missing their
|
155
175
|
# targets.
|
156
176
|
#
|
157
177
|
def self.remove_dead_links
|
158
|
-
removed_list = []
|
159
178
|
install_locations.each do |location|
|
160
|
-
next unless
|
161
|
-
files =
|
179
|
+
next unless location.exist?
|
180
|
+
files = location.entries.map { |f| location + f }
|
162
181
|
files.each do |file|
|
163
|
-
next unless
|
164
|
-
next if
|
165
|
-
|
166
|
-
|
182
|
+
next unless file.symlink?
|
183
|
+
next if file.readlink.exist?
|
184
|
+
next unless root_path(file.readlink)
|
185
|
+
file.delete
|
167
186
|
end
|
168
187
|
end
|
169
|
-
return removed_list
|
170
188
|
end
|
171
189
|
|
190
|
+
# Search through _directory_ and return the first static file found,
|
191
|
+
# nil otherwise.
|
192
|
+
#
|
193
|
+
def self.find_static_file(directory)
|
194
|
+
directory = Pathname.new(directory).expand_path
|
195
|
+
|
196
|
+
directory.find do |path|
|
197
|
+
return path if path.exist? && path.ftype == 'file'
|
198
|
+
end
|
199
|
+
return nil
|
200
|
+
end
|
201
|
+
|
172
202
|
# Delete each generated directory if there aren't any real files in
|
173
203
|
# them.
|
174
204
|
#
|
175
205
|
def self.remove_generated_directories
|
176
|
-
removed_list = []
|
177
206
|
generated_directories.each do |dir|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
if sf = find_static_file(dir)
|
183
|
-
|
184
|
-
else
|
185
|
-
|
186
|
-
|
187
|
-
end
|
207
|
+
# don't get rid of the linked config file
|
208
|
+
next if dir.basename.to_s == '.sundae'
|
209
|
+
remove_generated_stuff dir
|
210
|
+
|
211
|
+
# if sf = find_static_file(dir)
|
212
|
+
# puts "found static file: #{sf}"
|
213
|
+
# else
|
214
|
+
# dir.rmtree
|
215
|
+
# end
|
188
216
|
end
|
189
|
-
return removed_list
|
190
217
|
end
|
191
218
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
return path if File.exist?(path) && File.ftype(path) == 'file'
|
219
|
+
def self.remove_generated_files
|
220
|
+
generated_files.each do |fod|
|
221
|
+
# don't get rid of the linked config file
|
222
|
+
next if fod.basename.to_s == '.sundae'
|
223
|
+
remove_generated_stuff fod
|
198
224
|
end
|
199
|
-
return nil
|
200
225
|
end
|
201
226
|
|
227
|
+
def self.remove_generated_stuff(fod)
|
228
|
+
return unless fod.exist?
|
229
|
+
if fod.ftype == 'directory'
|
230
|
+
fod.each_child do |c|
|
231
|
+
remove_generated_stuff c
|
232
|
+
end
|
233
|
+
fod.rmdir if fod.children.empty?
|
234
|
+
else
|
235
|
+
return unless fod.symlink?
|
236
|
+
fod.delete if root_path(fod.readlink) # try to only delete sundae links
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
202
240
|
# Call minimally_create_links for each mnt.
|
203
241
|
#
|
204
242
|
def self.create_filesystem
|
205
|
-
mnt_list = []
|
206
243
|
all_mnts.each do |mnt|
|
207
|
-
|
244
|
+
install_location(mnt).expand_path.mkpath
|
208
245
|
minimally_create_links(mnt, install_location(mnt))
|
209
|
-
mnt_list << mnt
|
210
246
|
end
|
211
|
-
return mnt_list
|
212
247
|
end
|
213
248
|
|
214
249
|
# For each directory and file in _target_, create a link at <em>link_name</em>. If
|
@@ -240,11 +275,15 @@ module Sundae
|
|
240
275
|
# Starting at _dir_, walk up the directory hierarchy and return the
|
241
276
|
# directory that is contained in _@paths_.
|
242
277
|
#
|
243
|
-
def self.root_path(
|
244
|
-
|
278
|
+
def self.root_path(path)
|
279
|
+
path = Pathname.new(path).expand_path
|
280
|
+
last = path
|
281
|
+
path.ascend do |v|
|
282
|
+
return last if @paths.include? v
|
283
|
+
last = v
|
284
|
+
end
|
245
285
|
|
246
|
-
|
247
|
-
return (@paths.include?(parent)) ? dir : root_path(parent)
|
286
|
+
return nil
|
248
287
|
end
|
249
288
|
|
250
289
|
# Dispatch calls to create_directory_link and create_file_link.
|
@@ -266,7 +305,7 @@ module Sundae
|
|
266
305
|
def self.create_file_link(target, link_name)
|
267
306
|
raise ArgumentError, "#{target} does not exist" unless File.file?(target)
|
268
307
|
if File.exist?(link_name)
|
269
|
-
raise ArgumentError, "#{link_name} cannot be overwritten" unless File.symlink?(link_name)
|
308
|
+
raise ArgumentError, "#{link_name} cannot be overwritten for #{target}." unless File.symlink?(link_name)
|
270
309
|
if (not File.exist?(File.readlink(link_name)))
|
271
310
|
FileUtils.ln_sf(target, link_name)
|
272
311
|
else
|
@@ -285,18 +324,19 @@ module Sundae
|
|
285
324
|
#
|
286
325
|
def self.create_directory_link(target, link_name)
|
287
326
|
raise ArgumentError unless File.directory?(target)
|
288
|
-
if (not File.exist?(link_name)) ||
|
327
|
+
if (not File.exist?(link_name)) ||
|
328
|
+
(File.symlink?(link_name) && (not File.exist?(File.readlink(link_name))))
|
289
329
|
FileUtils.ln_sf(target, link_name)
|
290
330
|
else
|
291
331
|
case File.ftype(link_name)
|
292
332
|
when 'file'
|
293
|
-
raise "Could not link #{
|
333
|
+
raise "Could not link #{link_name} to #{target}: target exists."
|
294
334
|
when 'directory'
|
295
335
|
minimally_create_links(target, link_name)
|
296
336
|
when 'link'
|
297
337
|
case File.ftype(File.readlink(link_name))
|
298
338
|
when 'file'
|
299
|
-
raise "Could not link #{
|
339
|
+
raise "Could not link #{link_name} to #{target}: another link exists there."
|
300
340
|
when 'directory'
|
301
341
|
combine_directories(link_name, target, File.readlink(link_name))
|
302
342
|
end
|
@@ -308,6 +348,7 @@ module Sundae
|
|
308
348
|
# <em>target_path1</em> and <em>target_path2</em>.
|
309
349
|
#
|
310
350
|
def self.combine_directories(link_name, target_path1, target_path2)
|
351
|
+
raise unless File.symlink?(link_name)
|
311
352
|
return if target_path1 == target_path2
|
312
353
|
|
313
354
|
FileUtils.rm(link_name)
|
@@ -318,13 +359,13 @@ module Sundae
|
|
318
359
|
|
319
360
|
def self.update_filesystem
|
320
361
|
remove_dead_links
|
321
|
-
|
362
|
+
remove_generated_files
|
322
363
|
create_filesystem
|
323
364
|
end
|
324
365
|
|
325
366
|
def self.remove_filesystem
|
326
367
|
remove_dead_links
|
327
|
-
|
368
|
+
remove_generated_files
|
328
369
|
end
|
329
370
|
|
330
371
|
# Return an array of mnts that are installing to +path+.
|
data/test/test_sundae.rb
CHANGED
@@ -3,41 +3,34 @@ require 'test/unit'
|
|
3
3
|
$:.unshift File.join(File.dirname(__FILE__), "..", "bin") # add ../bin to the Ruby library path
|
4
4
|
$:.unshift File.join(File.dirname(__FILE__), "..", "lib") # ../lib
|
5
5
|
require 'sundae'
|
6
|
+
require 'pathname'
|
6
7
|
|
7
8
|
class TestSundae < Test::Unit::TestCase
|
8
9
|
|
9
|
-
@@testdir =
|
10
|
-
@@sandbox
|
11
|
-
@@static_dir =
|
12
|
-
@@mnts_dir
|
10
|
+
@@testdir = Pathname.new(__FILE__).parent.expand_path
|
11
|
+
@@sandbox = @@testdir + 'sandbox'
|
12
|
+
@@static_dir = @@sandbox + 'static'
|
13
|
+
@@mnts_dir = @@sandbox + 'mnts'
|
13
14
|
|
14
15
|
def setup
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
FileUtils.mkdir_p(File.join(@@mnts_dir, 'c2/d3/d31'))
|
26
|
-
File.open(File.join(@@mnts_dir, 'c1/d1/f11'), 'w')
|
27
|
-
File.open(File.join(@@mnts_dir, 'c1/d1/f12'), 'w')
|
28
|
-
File.open(File.join(@@mnts_dir, 'c1/d2/f21'), 'w')
|
29
|
-
File.open(File.join(@@mnts_dir, 'c2/d1/f13'), 'w')
|
30
|
-
File.open(File.join(@@mnts_dir, 'c2/d1/f14'), 'w')
|
31
|
-
File.open(File.join(@@mnts_dir, 'c2/d3/f31'), 'w')
|
32
|
-
['c1/d1', 'c1/d2', 'c2/d1', 'c2/d3'].each do |d|
|
33
|
-
File.open(File.join(@@mnts_dir, d, '.sundae_path'), 'w') do |f|
|
34
|
-
f.puts @@sandbox
|
35
|
-
end
|
16
|
+
@@sandbox.mkpath
|
17
|
+
@@static_dir.mkpath
|
18
|
+
|
19
|
+
(@@static_dir + 'static').open('w')
|
20
|
+
%w(c1 c2 c1/d1 c1/d2 c2/d1 c2/d3 c2/d3/d31).each do |x|
|
21
|
+
(@@mnts_dir + x).mkpath
|
22
|
+
end
|
23
|
+
|
24
|
+
%w(c1/d1/f11 c1/d1/f12 c1/d2/f21 c2/d1/f13 c2/d1/f14 c2/d3/f31).each do |x|
|
25
|
+
(@@mnts_dir + x).open('w')
|
36
26
|
end
|
37
27
|
|
38
|
-
|
28
|
+
%w(c1/d1 c1/d2 c2/d1 c2/d3).each do |d|
|
29
|
+
(@@mnts_dir + d + '.sundae_path').open('w') {|f| f.puts @@sandbox}
|
30
|
+
end
|
39
31
|
|
40
|
-
@@
|
32
|
+
@@path1 = @@sandbox + 'mnts'
|
33
|
+
@@config_file = @@sandbox + '.sundae'
|
41
34
|
File.open(@@config_file, 'w+') do |f|
|
42
35
|
f.puts "configatron.paths = [\"#{@@path1}\"]"
|
43
36
|
f.puts "configatron.ignore_rules = %w("
|
@@ -49,24 +42,24 @@ class TestSundae < Test::Unit::TestCase
|
|
49
42
|
end
|
50
43
|
|
51
44
|
def teardown
|
52
|
-
|
45
|
+
@@sandbox.rmtree
|
53
46
|
end
|
54
47
|
|
55
48
|
def test_class_all_mnts
|
56
49
|
all_mnts = Sundae.all_mnts
|
57
50
|
mnts = Sundae.mnts_in_path(@@path1)
|
58
51
|
mnts.each do |m|
|
59
|
-
assert all_mnts.include?(
|
52
|
+
assert all_mnts.include?(@@path1 + m)
|
60
53
|
end
|
61
54
|
end
|
62
55
|
|
63
56
|
def test_class_combine_directories
|
64
|
-
d1
|
65
|
-
d2
|
66
|
-
link =
|
57
|
+
d1 = @@mnts_dir + 'c1/d1'
|
58
|
+
d2 = @@mnts_dir + 'c1/d2'
|
59
|
+
link = @@sandbox + 'link'
|
67
60
|
FileUtils.ln_s(d1, link)
|
68
61
|
Sundae.combine_directories(link, d1, d2)
|
69
|
-
assert File.symlink?(
|
62
|
+
assert File.symlink?(link + 'f11')
|
70
63
|
end
|
71
64
|
|
72
65
|
def test_class_create_directory_link
|
@@ -125,6 +118,12 @@ class TestSundae < Test::Unit::TestCase
|
|
125
118
|
assert_equal 1, Sundae.generated_directories.size
|
126
119
|
end
|
127
120
|
|
121
|
+
def test_class_generated_files
|
122
|
+
Sundae.create_filesystem
|
123
|
+
# assert Sundae.generated_files.include?(File.join(@@sandbox, 'f11'))
|
124
|
+
assert_equal 7, Sundae.generated_files.size
|
125
|
+
end
|
126
|
+
|
128
127
|
def test_class_ignore_file_eh
|
129
128
|
assert Sundae.ignore_file?('.sundae_path')
|
130
129
|
assert Sundae.ignore_file?('..')
|
@@ -135,45 +134,45 @@ class TestSundae < Test::Unit::TestCase
|
|
135
134
|
end
|
136
135
|
|
137
136
|
def test_class_install_location
|
138
|
-
assert_equal Sundae.install_location('/')
|
139
|
-
assert_equal Sundae.install_location(
|
137
|
+
assert_equal Pathname.new(Dir.home), Sundae.install_location('/')
|
138
|
+
assert_equal @@sandbox, Sundae.install_location(@@mnts_dir + 'c1/d1')
|
140
139
|
end
|
141
140
|
|
142
141
|
def test_class_install_locations
|
143
|
-
assert_equal
|
142
|
+
assert_equal [@@sandbox], Sundae.install_locations
|
144
143
|
end
|
145
144
|
|
146
145
|
def test_class_load_config_file
|
147
146
|
sundae_paths = Sundae.instance_variable_get(:@paths)
|
148
|
-
assert_equal sundae_paths[0],
|
147
|
+
assert_equal sundae_paths[0], Pathname.new(@@path1).expand_path
|
149
148
|
end
|
150
149
|
|
151
150
|
def test_class_minimally_create_links
|
152
151
|
c1 = File.join(@@mnts_dir, 'c1')
|
153
152
|
c2 = File.join(@@mnts_dir, 'c2')
|
154
153
|
Sundae.minimally_create_links(c1, @@sandbox)
|
155
|
-
assert
|
156
|
-
assert
|
154
|
+
assert((@@sandbox + 'd1').symlink?)
|
155
|
+
assert((@@sandbox + 'd2').symlink?)
|
157
156
|
Sundae.minimally_create_links(c2, @@sandbox)
|
158
|
-
assert
|
159
|
-
assert
|
160
|
-
assert
|
161
|
-
assert
|
162
|
-
assert
|
157
|
+
assert((@@sandbox + 'd1').directory?)
|
158
|
+
assert((@@sandbox + 'd1/f11').symlink?)
|
159
|
+
assert((@@sandbox + 'd1/f14').symlink?)
|
160
|
+
assert((@@sandbox + 'd2').symlink?)
|
161
|
+
assert((@@sandbox + 'd3').symlink?)
|
163
162
|
end
|
164
163
|
|
165
164
|
def test_class_mnts_in_path
|
166
|
-
assert_equal
|
165
|
+
assert_equal ['c1/d1', 'c1/d2', 'c2/d1', 'c2/d3'].map {|x| Pathname.new(x)},
|
166
|
+
Sundae.mnts_in_path(@@path1)
|
167
167
|
end
|
168
168
|
|
169
169
|
def test_class_remove_dead_links
|
170
|
-
|
171
|
-
|
170
|
+
(@@sandbox + 'temp_file').open('w')
|
171
|
+
(@@sandbox + 'perm_file').open('w')
|
172
172
|
FileUtils.ln_s(File.join(@@sandbox, 'temp_file'), File.join(@@sandbox, 'link'))
|
173
|
-
|
174
|
-
|
175
|
-
assert
|
176
|
-
assert File.exist?(File.join(@@sandbox, 'perm_file'))
|
173
|
+
(@@sandbox + 'temp_file').delete
|
174
|
+
assert ! (@@sandbox + 'link').exist?
|
175
|
+
assert (@@sandbox + 'perm_file').exist?
|
177
176
|
end
|
178
177
|
|
179
178
|
def test_class_remove_generated_directories
|
@@ -185,12 +184,9 @@ class TestSundae < Test::Unit::TestCase
|
|
185
184
|
end
|
186
185
|
|
187
186
|
def test_class_root_path
|
188
|
-
assert_equal
|
189
|
-
assert_equal
|
190
|
-
|
191
|
-
assert_raise ArgumentError do
|
192
|
-
Sundae.root_path('/')
|
193
|
-
end
|
187
|
+
assert_equal @@mnts_dir +'c1', Sundae.root_path(@@mnts_dir + 'c1')
|
188
|
+
assert_equal @@mnts_dir + 'c1', Sundae.root_path(@@mnts_dir + 'c1/d1')
|
189
|
+
assert_equal nil, Sundae.root_path('/')
|
194
190
|
end
|
195
191
|
|
196
192
|
def test_class_create_link
|
data/unison/common
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
fastcheck = true
|
2
|
+
|
3
|
+
# Roots of the synchronization
|
4
|
+
include local_mnt_path
|
5
|
+
|
6
|
+
ui = text
|
7
|
+
log = false
|
8
|
+
auto = true
|
9
|
+
|
10
|
+
# Names and paths to ignore:
|
11
|
+
ignore = Name temp.*
|
12
|
+
ignore = Name *~
|
13
|
+
ignore = Name .*~
|
14
|
+
ignore = Name *.o
|
15
|
+
ignore = Name *.tmp
|
16
|
+
ignore = Name .emacs_autosaves
|
17
|
+
ignore = Name .emacs_backups
|
@@ -0,0 +1,12 @@
|
|
1
|
+
include common
|
2
|
+
|
3
|
+
root = ssh://donmarch.org//home/14129/users/don%donmarch.org/var/unison/mnts
|
4
|
+
sshargs = "-l don%donmarch.org"
|
5
|
+
|
6
|
+
path = linux
|
7
|
+
path = nix
|
8
|
+
path = personal
|
9
|
+
path = personal_private
|
10
|
+
path = proprietorship
|
11
|
+
path = personal_archive
|
12
|
+
path = reference
|
data/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sundae
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
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: 2012-02-
|
12
|
+
date: 2012-02-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: highline
|
16
|
-
requirement: &
|
16
|
+
requirement: &79306580 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.6.11
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *79306580
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: configatron
|
27
|
-
requirement: &
|
27
|
+
requirement: &79306020 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.9.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *79306020
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rdoc
|
38
|
-
requirement: &
|
38
|
+
requirement: &79305190 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '3.12'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *79305190
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bones
|
49
|
-
requirement: &
|
49
|
+
requirement: &79303240 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: 3.7.3
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *79303240
|
58
58
|
description: Mix collections of files while maintaining complete separation.
|
59
59
|
email: don@ohspite.net
|
60
60
|
executables:
|
@@ -67,6 +67,8 @@ extra_rdoc_files:
|
|
67
67
|
- !binary |-
|
68
68
|
YmluL3N1bmRhZQ==
|
69
69
|
files:
|
70
|
+
- !binary |-
|
71
|
+
LmdpdGlnbm9yZQ==
|
70
72
|
- !binary |-
|
71
73
|
Q0hBTkdFTE9H
|
72
74
|
- !binary |-
|
@@ -81,6 +83,10 @@ files:
|
|
81
83
|
bGliL3N1bmRhZS5yYg==
|
82
84
|
- !binary |-
|
83
85
|
dGVzdC90ZXN0X3N1bmRhZS5yYg==
|
86
|
+
- !binary |-
|
87
|
+
dW5pc29uL2NvbW1vbg==
|
88
|
+
- !binary |-
|
89
|
+
dW5pc29uL210X2V4YW1wbGUucHJm
|
84
90
|
- !binary |-
|
85
91
|
dmVyc2lvbi50eHQ=
|
86
92
|
homepage: https://github.com/ohspite/sundae
|