xdg 1.0.0 → 2.0.0
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/.ruby +33 -0
- data/APACHE2.txt +204 -0
- data/{HISTORY → HISTORY.rdoc} +14 -0
- data/README.rdoc +149 -0
- data/lib/xdg.rb +16 -228
- data/lib/xdg/base_dir.rb +220 -0
- data/lib/xdg/base_dir/extended.rb +20 -0
- data/lib/xdg/base_dir/global_variables.rb +18 -0
- data/lib/xdg/base_dir/legacy.rb +72 -0
- data/lib/xdg/base_dir/mixin.rb +84 -0
- data/lib/xdg/version.rb +3 -0
- data/qed/01_base_dir.rdoc +77 -0
- data/qed/02_base_dir_extended.rb +39 -0
- data/qed/03_base_dir_mixin.rb +19 -0
- data/qed/applique/fakeroot.rb +15 -0
- data/qed/fixtures/fakeroot/etc/xdg/bar.config +1 -0
- data/qed/fixtures/fakeroot/home/.cache/foo.cache +1 -0
- data/qed/fixtures/fakeroot/home/.config/foo.config +1 -0
- data/qed/fixtures/fakeroot/home/.local/share/foo.dat +1 -0
- data/qed/fixtures/fakeroot/home/joe/foo.txt +1 -0
- data/qed/fixtures/fakeroot/usr/share/bar.dat +1 -0
- data/test/{test_xdg.rb → test_xdg_legacy.rb} +6 -4
- metadata +49 -41
- data/COPYING +0 -789
- data/MANIFEST +0 -24
- data/README +0 -97
- data/lib/xdg/compat.rb +0 -66
- data/lib/xdg/extended.rb +0 -84
- data/meta/authors +0 -1
- data/meta/collection +0 -1
- data/meta/contact +0 -1
- data/meta/description +0 -2
- data/meta/homepage +0 -1
- data/meta/name +0 -1
- data/meta/repository +0 -1
- data/meta/summary +0 -1
- data/meta/title +0 -1
- data/meta/version +0 -1
- data/script/test +0 -4
data/lib/xdg/base_dir.rb
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
module XDG
|
2
|
+
|
3
|
+
# Base Directory Standard
|
4
|
+
class BaseDir
|
5
|
+
|
6
|
+
# Try to get information from Ruby's install configuration.
|
7
|
+
require 'rbconfig'
|
8
|
+
|
9
|
+
sysconfdir = ::Config::CONFIG['sysconfdir'] || '/etc'
|
10
|
+
datadir = ::Config::CONFIG['datadir'] || '/usr/share'
|
11
|
+
|
12
|
+
# Standard defaults for locations.
|
13
|
+
DEFAULTS = {
|
14
|
+
'XDG_DATA_HOME' => ['~/.local/share'],
|
15
|
+
'XDG_DATA_DIRS' => ['/usr/local/share', datadir],
|
16
|
+
'XDG_CONFIG_HOME' => ['~/.config'],
|
17
|
+
'XDG_CONFIG_DIRS' => [File.join(sysconfdir,'xdg'), sysconfdir],
|
18
|
+
'XDG_CACHE_HOME' => ['~/.cache'],
|
19
|
+
'XDG_CACHE_DIRS' => ['/tmp']
|
20
|
+
}
|
21
|
+
|
22
|
+
# BaseDir iterates over directory paths.
|
23
|
+
include Enumerable
|
24
|
+
|
25
|
+
# Shortcut for `BaseDir.new`.
|
26
|
+
def self.[](*env)
|
27
|
+
new(*env)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Initialize new instance of BaseDir class.
|
31
|
+
def initialize(*env)
|
32
|
+
@environment_variables = []
|
33
|
+
env.each do |v|
|
34
|
+
v = v.to_s.upcase
|
35
|
+
if v !~ /_/
|
36
|
+
@environment_variables << 'XDG_' + v + '_HOME'
|
37
|
+
@environment_variables << 'XDG_' + v + '_DIRS'
|
38
|
+
else
|
39
|
+
@environment_variables << 'XDG_' + v
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# The environment variables being referenced.
|
45
|
+
#
|
46
|
+
# @return [Array] list of XDG environment variable names
|
47
|
+
def environment_variables
|
48
|
+
@environment_variables
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns a complete list of directories.
|
52
|
+
def to_a
|
53
|
+
environment_variables.map do |v|
|
54
|
+
if paths = ENV[v]
|
55
|
+
dirs = paths.split(/[:;]/)
|
56
|
+
else
|
57
|
+
dirs = DEFAULTS[v]
|
58
|
+
end
|
59
|
+
dirs.map{ |path| expand(path) }
|
60
|
+
end.flatten
|
61
|
+
end
|
62
|
+
|
63
|
+
# BaseDir is essentially an array.
|
64
|
+
alias_method :to_ary, :to_a
|
65
|
+
|
66
|
+
# Number of directory paths.
|
67
|
+
def size
|
68
|
+
to_a.size
|
69
|
+
end
|
70
|
+
|
71
|
+
# Iterate of each directory.
|
72
|
+
def each(&block)
|
73
|
+
to_a.each(&block)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns a complete list of directories.
|
77
|
+
def list
|
78
|
+
to_a
|
79
|
+
end
|
80
|
+
|
81
|
+
# List of directories as Pathanme objects.
|
82
|
+
#
|
83
|
+
# @return [Array<Pathname>] list of directories as Pathname objects
|
84
|
+
def paths
|
85
|
+
map{ |dir| Pathname.new(dir) }
|
86
|
+
end
|
87
|
+
|
88
|
+
# Return array of matching files or directories
|
89
|
+
# in any of the resource locations, starting with
|
90
|
+
# the home directory and searching outward into
|
91
|
+
# system directories.
|
92
|
+
#
|
93
|
+
# Unlike #select, this doesn't take a block and each
|
94
|
+
# additional glob argument is treated as a logical-or.
|
95
|
+
#
|
96
|
+
# XDG[:DATA].glob("stick/*.rb", "stick/*.yaml")
|
97
|
+
#
|
98
|
+
def glob(*glob_and_flags)
|
99
|
+
glob, flags = *parse_arguments(*glob_and_flags)
|
100
|
+
find = []
|
101
|
+
list.each do |dir|
|
102
|
+
glob.each do |pattern|
|
103
|
+
find.concat(Dir.glob(File.join(dir, pattern), flags))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
find.uniq
|
107
|
+
end
|
108
|
+
|
109
|
+
# Return array of matching files or directories
|
110
|
+
# in any of the resource locations, starting with
|
111
|
+
# the home directory and searching outward into
|
112
|
+
# system directories.
|
113
|
+
#
|
114
|
+
# String parameters are joined into a pathname
|
115
|
+
# while Integers and Symbols treated as flags.
|
116
|
+
#
|
117
|
+
# For example, the following are equivalent:
|
118
|
+
#
|
119
|
+
# XDG::BaseDir[:DATA,:HOME].select('stick/units', File::FNM_CASEFOLD)
|
120
|
+
#
|
121
|
+
# XDG::BaseDir[:DATA,:HOME].select('stick', 'units', :casefold)
|
122
|
+
#
|
123
|
+
def select(*glob_and_flags, &block)
|
124
|
+
glob, flag = *parse_arguments(*glob_and_flags)
|
125
|
+
find = []
|
126
|
+
list.each do |dir|
|
127
|
+
path = File.join(dir, *glob)
|
128
|
+
hits = Dir.glob(path, flag)
|
129
|
+
hits = hits.select(&block) if block_given?
|
130
|
+
find.concat(hits)
|
131
|
+
end
|
132
|
+
find.uniq
|
133
|
+
end
|
134
|
+
|
135
|
+
# Find a file or directory. This works just like #select
|
136
|
+
# except that it returns the first match found.
|
137
|
+
#
|
138
|
+
# TODO: It would be more efficient to traverse the dirs and use #fnmatch.
|
139
|
+
def find(*glob_and_flags, &block)
|
140
|
+
glob, flag = *parse_arguments(*glob_and_flags)
|
141
|
+
find = nil
|
142
|
+
list.each do |dir|
|
143
|
+
path = File.join(dir, *glob)
|
144
|
+
hits = Dir.glob(path, flag)
|
145
|
+
hits = hits.select(&block) if block_given?
|
146
|
+
find = hits.first
|
147
|
+
break if find
|
148
|
+
end
|
149
|
+
find
|
150
|
+
end
|
151
|
+
|
152
|
+
# @return [String] envinronment values.
|
153
|
+
def to_s
|
154
|
+
environment_variables.map{ |v| ENV[v] || DEFAULTS[v] }.join(':')
|
155
|
+
end
|
156
|
+
|
157
|
+
# @return [Pathname] pathname of first directory
|
158
|
+
def to_path
|
159
|
+
Pathname.new(to_s)
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
def env
|
164
|
+
environment_variables.map{ |v| ENV[v] }.join(':')
|
165
|
+
end
|
166
|
+
|
167
|
+
#
|
168
|
+
attr :subdirectory
|
169
|
+
|
170
|
+
#
|
171
|
+
def subdirectory=(path)
|
172
|
+
@subdirectory = path.to_s
|
173
|
+
end
|
174
|
+
|
175
|
+
#
|
176
|
+
def with_subdirectory(path)
|
177
|
+
@subdirectory = path if path
|
178
|
+
self
|
179
|
+
end
|
180
|
+
|
181
|
+
private
|
182
|
+
|
183
|
+
def parse_arguments(*glob_and_flags)
|
184
|
+
glob, flags = *glob_and_flags.partition{ |e| String===e }
|
185
|
+
glob = ['**/*'] if glob.empty?
|
186
|
+
flag = flags.inject(0) do |m, f|
|
187
|
+
if Symbol === f
|
188
|
+
m + File::const_get("FNM_#{f.to_s.upcase}")
|
189
|
+
else
|
190
|
+
m + f.to_i
|
191
|
+
end
|
192
|
+
end
|
193
|
+
return glob, flag
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
def expand(path)
|
198
|
+
if subdirectory
|
199
|
+
File.expand_path(File.join(path, subdirectory))
|
200
|
+
else
|
201
|
+
File.expand_path(path)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# If Pathname is referenced the library is automatically loaded.
|
206
|
+
def self.const_missing(const)
|
207
|
+
if const == :Pathname
|
208
|
+
require 'pathname'
|
209
|
+
::Pathname
|
210
|
+
else
|
211
|
+
super(const)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
# Copyright (c) 2008,2011 Thomas Sawyer
|
220
|
+
# Distributed under the terms of the APACHE 2.0 license.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module XDG
|
2
|
+
|
3
|
+
# Base directory interface class.
|
4
|
+
class BaseDir
|
5
|
+
|
6
|
+
#
|
7
|
+
DEFAULTS['XDG_RESOURCE_HOME'] = ['~/.local']
|
8
|
+
DEFAULTS['XDG_RESOURCE_DIRS'] = ['/usr/local','/usr']
|
9
|
+
|
10
|
+
# Working directory
|
11
|
+
# TODO: Not sure about these defaults
|
12
|
+
DEFAULTS['XDG_CONFIG_WORK'] = ['.config','config']
|
13
|
+
DEFAULTS['XDG_CACHE_WORK'] = ['.tmp','tmp']
|
14
|
+
DEFAULTS['XDG_RESOURCE_WORK'] = ['.local']
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
# Copyright (c) 2008,2011 Thomas Sawyer
|
20
|
+
# Distributed under the terms of the APACHE 2.0 license.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
if RUBY_VERSION > '1.9'
|
2
|
+
require_relative 'base_dir'
|
3
|
+
else
|
4
|
+
require 'xdg/base_dir'
|
5
|
+
end
|
6
|
+
|
7
|
+
$XDG_DATA = XDG::BaseDir.new('DATA')
|
8
|
+
$XDG_DATA_HOME = XDG::BaseDir.new('DATA', 'HOME')
|
9
|
+
$XDG_DATA_DIRS = XDG::BaseDir.new('DATA', 'DIRS')
|
10
|
+
|
11
|
+
$XDG_CONFIG = XDG::BaseDir.new('CONFIG')
|
12
|
+
$XDG_CONFIG_HOME = XDG::BaseDir.new('CONFIG', 'HOME')
|
13
|
+
$XDG_CONFIG_DIRS = XDG::BaseDir.new('CONFIG', 'DIRS')
|
14
|
+
|
15
|
+
$XDG_CACHE = XDG::BaseDir.new('CACHE')
|
16
|
+
$XDG_CACHE_HOME = XDG::BaseDir.new('CACHE', 'HOME')
|
17
|
+
$XDG_CACHE_DIRS = XDG::BaseDir.new('CACHE', 'DIRS')
|
18
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module XDG
|
2
|
+
class BaseDir
|
3
|
+
# Legacy API can serve as a stop gap until a developer
|
4
|
+
# has time to update an program already using XDG.
|
5
|
+
#
|
6
|
+
# Do NOT use this module for future development!!!
|
7
|
+
module Legacy
|
8
|
+
#
|
9
|
+
require 'xdg'
|
10
|
+
require 'xdg/base_dir/extended'
|
11
|
+
|
12
|
+
#
|
13
|
+
extend self
|
14
|
+
|
15
|
+
#
|
16
|
+
def home
|
17
|
+
File.expand_path('~')
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
def data
|
22
|
+
obj = XDG['DATA']
|
23
|
+
class << obj
|
24
|
+
def home
|
25
|
+
XDG['DATA_HOME'].to_a.first
|
26
|
+
end
|
27
|
+
def dirs
|
28
|
+
XDG['DATA_DIRS'].to_a
|
29
|
+
end
|
30
|
+
end
|
31
|
+
return obj
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
def config
|
36
|
+
obj = XDG['CONFIG']
|
37
|
+
class << obj
|
38
|
+
def home
|
39
|
+
XDG['CONFIG_HOME'].to_a.first
|
40
|
+
end
|
41
|
+
def dirs
|
42
|
+
XDG['CONFIG_DIRS'].to_a
|
43
|
+
end
|
44
|
+
def work
|
45
|
+
XDG['CONFIG_WORK'].to_a
|
46
|
+
end
|
47
|
+
end
|
48
|
+
return obj
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
def cache
|
53
|
+
obj = XDG['CACHE']
|
54
|
+
class << obj
|
55
|
+
def home
|
56
|
+
XDG['CACHE_HOME'].to_a.first
|
57
|
+
end
|
58
|
+
def dirs
|
59
|
+
XDG['CACHE_DIRS'].to_a
|
60
|
+
end
|
61
|
+
def work
|
62
|
+
XDG['CACHE_WORK'].to_a
|
63
|
+
end
|
64
|
+
end
|
65
|
+
return obj
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
extend BaseDir::Legacy
|
72
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module XDG
|
2
|
+
class BaseDir
|
3
|
+
#
|
4
|
+
# The BaseDir::Mixin module can be used to add XDG base directory
|
5
|
+
# methods to your own classes.
|
6
|
+
#
|
7
|
+
# class MyAppConfig
|
8
|
+
# include XDG::BaseDir::Mixin
|
9
|
+
#
|
10
|
+
# def subdirectory
|
11
|
+
# 'myapp'
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# c = MyAppConfig.new
|
16
|
+
#
|
17
|
+
# c.config.home.to_s #=> '~/.config/myapp'
|
18
|
+
#
|
19
|
+
module Mixin
|
20
|
+
|
21
|
+
# @todo do we need this?
|
22
|
+
extend self
|
23
|
+
|
24
|
+
# Override this method to change the subdirectory of the mixin.
|
25
|
+
def subdirectory
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
def home
|
31
|
+
File.expand_path('~')
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
def data
|
36
|
+
obj = XDG['DATA'].with_subdirectory(subdirectory)
|
37
|
+
class << obj
|
38
|
+
def home
|
39
|
+
XDG['DATA_HOME'].with_subdirectory(subdirectory)
|
40
|
+
end
|
41
|
+
def dirs
|
42
|
+
XDG['DATA_DIRS'].with_subdirectory(subdirectory)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return obj
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
def config
|
50
|
+
obj = XDG['CONFIG'].with_subdirectory(subdirectory)
|
51
|
+
class << obj
|
52
|
+
def home
|
53
|
+
XDG['CONFIG_HOME'].with_subdirectory(subdirectory)
|
54
|
+
end
|
55
|
+
def dirs
|
56
|
+
XDG['CONFIG_DIRS'].with_subdirectory(subdirectory)
|
57
|
+
end
|
58
|
+
def work
|
59
|
+
XDG['CONFIG_WORK'].with_subdirectory(subdirectory)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
return obj
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
def cache
|
67
|
+
obj = XDG['CACHE'].with_subdirectory(subdirectory)
|
68
|
+
class << obj
|
69
|
+
def home
|
70
|
+
XDG['CACHE_HOME'].with_subdirectory(subdirectory)
|
71
|
+
end
|
72
|
+
def dirs
|
73
|
+
XDG['CACHE_DIRS'].with_subdirectory(subdirectory)
|
74
|
+
end
|
75
|
+
def work
|
76
|
+
XDG['CACHE_WORK'].with_subdirectory(subdirectory)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
return obj
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/xdg/version.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
= XDG Base Directory Standard
|
2
|
+
|
3
|
+
The 2.0 API is much a great deal more concise than the original
|
4
|
+
0.0+ and 1.0+ APIs. It consists primarily of a single
|
5
|
+
interface method `XDG[]`. Yet all the functionality of the older
|
6
|
+
API remain and then some.
|
7
|
+
|
8
|
+
First we need to require the library.
|
9
|
+
|
10
|
+
require 'xdg'
|
11
|
+
|
12
|
+
In the applique we have setup a fake root directory with
|
13
|
+
coorepsonding environment settings to use as test fixtures.
|
14
|
+
|
15
|
+
== Data Paths
|
16
|
+
|
17
|
+
=== Home
|
18
|
+
|
19
|
+
XDG['DATA_HOME'].env.assert == ENV['XDG_DATA_HOME'].to_s
|
20
|
+
XDG['DATA_HOME'].environment_variables.assert == ['XDG_DATA_HOME']
|
21
|
+
|
22
|
+
Looking at the data home location by default it should be point to
|
23
|
+
our joe user's home directory under `.local/share`.
|
24
|
+
|
25
|
+
XDG['DATA_HOME'].to_a.assert == [$froot + 'home/joe/.local/share']
|
26
|
+
|
27
|
+
=== Dirs
|
28
|
+
|
29
|
+
XDG['DATA_DIRS'].env.assert == ENV['XDG_DATA_DIRS'].to_s
|
30
|
+
XDG['DATA_DIRS'].environment_variables.assert == ['XDG_DATA_DIRS']
|
31
|
+
|
32
|
+
Looking at the system data locations
|
33
|
+
|
34
|
+
XDG['DATA_DIRS'].to_a.assert == [$froot + 'usr/share']
|
35
|
+
|
36
|
+
=== Combined
|
37
|
+
|
38
|
+
XDG['DATA'].environment_variables.assert == ['XDG_DATA_HOME', 'XDG_DATA_DIRS']
|
39
|
+
|
40
|
+
Lookking at both data location combined
|
41
|
+
|
42
|
+
XDG['DATA'].to_a.assert == [$froot + 'home/joe/.local/share', $froot + 'usr/share']
|
43
|
+
|
44
|
+
|
45
|
+
== Config Paths
|
46
|
+
|
47
|
+
=== Home
|
48
|
+
|
49
|
+
XDG['CONFIG_HOME'].env.assert == ENV['XDG_CONFIG_HOME'].to_s
|
50
|
+
XDG['CONFIG_HOME'].to_a.assert == [$froot + 'home/joe/.config']
|
51
|
+
|
52
|
+
=== Dirs
|
53
|
+
|
54
|
+
XDG['CONFIG_DIRS'].env.assert == ENV['XDG_CONFIG_DIRS'].to_s
|
55
|
+
XDG['CONFIG_DIRS'].to_a.assert == [$froot + 'etc/xdg', $froot + 'etc']
|
56
|
+
|
57
|
+
=== Combined
|
58
|
+
|
59
|
+
XDG['CONFIG'].to_a.assert == [$froot + 'home/joe/.config', $froot + 'etc/xdg', $froot + 'etc']
|
60
|
+
|
61
|
+
|
62
|
+
== Cache Paths
|
63
|
+
|
64
|
+
=== Home
|
65
|
+
|
66
|
+
XDG['CACHE_HOME'].env.assert == ENV['XDG_CACHE_HOME'].to_s
|
67
|
+
XDG['CACHE_HOME'].to_a.assert == [$froot + 'home/joe/.cache']
|
68
|
+
|
69
|
+
=== Dirs
|
70
|
+
|
71
|
+
XDG['CACHE_DIRS'].env.assert == ENV['XDG_CACHE_DIRS'].to_s
|
72
|
+
XDG['CACHE_DIRS'].to_a.assert == [$froot + 'tmp']
|
73
|
+
|
74
|
+
=== Combined
|
75
|
+
|
76
|
+
XDG['CACHE'].to_a.assert == [$froot + 'home/joe/.cache', $froot + 'tmp']
|
77
|
+
|