augeas 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/NEWS ADDED
@@ -0,0 +1,41 @@
1
+ 0.6.0 - 2014-01-19
2
+ - merge pull request by mapleoin (https://github.com/mapleoin):
3
+ raise exceptions instead of returning error codes
4
+
5
+ 0.5.0 - 2013-03-12
6
+ - add libxml2 headers and library to Makefile
7
+ - add libxml2-devel build req to rpm spec
8
+ - split out header, add memstream utils from Augeas
9
+ - integrate with Travis CI
10
+ - Takefile: add gem authors metadata
11
+ - Augeas::transform: add .lns suffix if a module name is passed
12
+ to match aug_transform behaviour
13
+ - add Augeas::clearm
14
+ - add Augeas::context and Augeas::context=
15
+ - add Augeas::label
16
+ - add Augeas::rename
17
+ - add Augeas::srun
18
+ - add Augeas::text_retrieve
19
+ - add Augeas::text_store
20
+
21
+ 0.4.1 - 2011-03-29
22
+ - remove object files from release tarball
23
+
24
+ 0.4.0 - 2011-03-25
25
+ - set can now set multiple elements at once
26
+ - expose aug_setm as Augeas#setm
27
+ - expose error functions through Augeas#error
28
+ - expose aug_span as Augeas#span
29
+
30
+ 0.3.0 - 2009-08-12
31
+ - Require augeas >= 0.5.1
32
+ - Bindings for aug_load, aug_defvar, and aug_defnode
33
+ - Map flags AUG_NO_STDINC, AUG_NO_LOAD, AUG_NO_MODL_AUTOLOAD
34
+ - Augeas::transform: convenience method for setting up transforms
35
+ - Augeas::set: allow passing in nil as the value
36
+ - Augeas::open: make args optional, accept block
37
+ - Exception raising versions of set, load, and save
38
+
39
+ 0.2.0 - 2008-08-26
40
+ Details for this and earlier releases need to be extracted from the
41
+ history of the git repo
@@ -0,0 +1,86 @@
1
+ = Ruby bindings for augeas
2
+
3
+ The class Augeas provides bindings to augeas [http://augeas.net] library.
4
+
5
+ == Usage: Setting Data
6
+ Augeas::create do |aug|
7
+ aug.set("/files/etc/sysconfig/firstboot/RUN_FIRSTBOOT", "YES")
8
+ unless aug.save
9
+ raise IOError, "Failed to save changes"
10
+ end
11
+ end
12
+
13
+ == Usage: Accessing Data
14
+ firstboot = Augeas::create {
15
+ |aug| aug.get("/files/etc/sysconfig/firstboot/RUN_FIRSTBOOT") }
16
+
17
+
18
+ == Usage: Removing Data
19
+ Augeas::create do |aug|
20
+ aug.rm("/files/etc/sysconfig/firstboot/RUN_FIRSTBOOT")
21
+ unless aug.save
22
+ raise IOError, "Failed to save changes"
23
+ end
24
+ end
25
+
26
+ == Usage: Minimal Setup with a Custom Root
27
+
28
+ By passing using the +:no_modl_autoload+ flag, no files are read on
29
+ startup; that allows setting up a custom transform.
30
+
31
+ Augeas::create(:root => "/var/tmp/augeas-root",
32
+ :loadpath => "/usr/local/share/mylenses",
33
+ :no_modl_autoload => true) do |aug|
34
+ aug.transform(:lens => "Aliases.lns", :incl => "/etc/aliases")
35
+ aug.load
36
+ aug.get("/files/etc/aliases/*[name = 'postmaster']/value")
37
+ end
38
+
39
+
40
+ == Deprecation Warning
41
+
42
+ The Augeas API has been heavily rewritten in order to better support
43
+ errors.
44
+
45
+ To use the new API, just use <tt>Augeas::create</tt> instead of
46
+ <tt>Augeas::open</tt>. This is the documentation for the
47
+ <tt>Augeas::create</tt> method.
48
+
49
+ Create a new Augeas instance and return it.
50
+
51
+ Use <tt>:root</tt> as the filesystem root. If <tt>:root</tt> is
52
+ <tt>nil</tt>, use the value of the environment variable
53
+ <tt>AUGEAS_ROOT</tt>. If that doesn't exist either, use "/".
54
+
55
+ <tt>:loadpath</tt> is a colon-spearated list of directories that modules
56
+ should be searched in. This is in addition to the standard load path and
57
+ the directories in <tt>AUGEAS_LENS_LIB</tt>.
58
+
59
+ The following flags can be specified in a hash. They all default to
60
+ false and can be enabled by setting them to true
61
+
62
+ <tt>:type_check</tt> - typecheck lenses (since it can be very expensive
63
+ it is not done by default)
64
+
65
+ <tt>:no_stdinc</tt> - do not use the builtin load path for modules
66
+
67
+ <tt>:no_load</tt> - do not load the tree during the initialization phase
68
+
69
+ <tt>:no_modl_autoload</tt> - do not load the tree during the
70
+ initialization phase
71
+
72
+ <tt>:enable_span</tt> - track the span in the input nodes
73
+
74
+ <tt>:save_mode</tt> can be one of <tt>:backup</tt>, <tt>:newfile</tt>,
75
+ <tt>:noop</tt> as explained below.
76
+
77
+ :noop - make save a no-op process, just record what would have changed
78
+
79
+ :backup - keep the original file with an .augsave extension
80
+
81
+ :newfile - save changes into a file with an .augnew extension and do
82
+ not overwrite the original file.
83
+
84
+ When a block is given, the Augeas instance is passed as the only
85
+ argument into the block and closed when the block exits. With no block,
86
+ the Augeas instance is returned.
@@ -0,0 +1,96 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rake/clean'
4
+ require 'rdoc/task'
5
+ require 'rake/testtask'
6
+ require 'rubygems/package_task'
7
+
8
+ GEM_NAME='augeas'
9
+ GEM_VERSION='0.6.0'
10
+ EXT_CONF='ext/augeas/extconf.rb'
11
+ MAKEFILE="ext/augeas/Makefile"
12
+ AUGEAS_MODULE="ext/augeas/_augeas.so"
13
+ SPEC_FILE="augeas.spec"
14
+ AUGEAS_SRC=AUGEAS_MODULE.gsub(/.so$/, ".c")
15
+
16
+ #
17
+ # Building the actual bits
18
+ #
19
+ CLEAN.include [ "**/*~",
20
+ "ext/**/*.o", AUGEAS_MODULE,
21
+ "ext/**/depend" ]
22
+
23
+ CLOBBER.include [ "config.save",
24
+ "ext/**/mkmf.log",
25
+ MAKEFILE ]
26
+
27
+ file MAKEFILE => EXT_CONF do |t|
28
+ Dir::chdir(File::dirname(EXT_CONF)) do
29
+ unless sh "ruby #{File::basename(EXT_CONF)}"
30
+ $stderr.puts "Failed to run extconf"
31
+ break
32
+ end
33
+ end
34
+ end
35
+ file AUGEAS_MODULE => [ MAKEFILE, AUGEAS_SRC ] do |t|
36
+ Dir::chdir(File::dirname(EXT_CONF)) do
37
+ unless sh "make"
38
+ $stderr.puts "make failed"
39
+ break
40
+ end
41
+ end
42
+ end
43
+ desc "Build the native library"
44
+ task :build => AUGEAS_MODULE
45
+
46
+ #
47
+ # Testing
48
+ #
49
+ Rake::TestTask.new(:test) do |t|
50
+ t.test_files = FileList['tests/tc_*.rb']
51
+ t.libs = [ 'lib', 'ext/augeas' ]
52
+ end
53
+ task :test => :build
54
+
55
+
56
+ #
57
+ # Generate the documentation
58
+ #
59
+ RDoc::Task.new do |rd|
60
+ rd.main = "README.rdoc"
61
+ rd.rdoc_dir = "doc/site/api"
62
+ rd.rdoc_files.include("README.rdoc", "ext/**/*.[ch]","lib/**/*.rb")
63
+ end
64
+
65
+ #
66
+ # Packaging
67
+ #
68
+ PKG_FILES = FileList[
69
+ "Rakefile", "COPYING","README.rdoc", "NEWS",
70
+ "ext/**/*.[ch]", "lib/**/*.rb", "ext/**/MANIFEST", "ext/**/extconf.rb",
71
+ "tests/**/*",
72
+ "spec/**/*"
73
+ ]
74
+
75
+ SPEC = Gem::Specification.new do |s|
76
+ s.name = GEM_NAME
77
+ s.version = GEM_VERSION
78
+ s.email = "dot.doom@gmail.com"
79
+ s.homepage = "http://augeas.net/"
80
+ s.summary = "Ruby bindings for augeas"
81
+ s.authors = [ "Bryan Kearney", "David Lutterkort", "Ionut Artarisi", "Artem Sheremet" ]
82
+ s.files = PKG_FILES
83
+ s.licenses = ['LGPLv2']
84
+ s.required_ruby_version = '>= 1.8.7'
85
+ s.extensions = "ext/augeas/extconf.rb"
86
+ s.description = "Provides bindings for augeas."
87
+ s.add_development_dependency "rake"
88
+ s.add_development_dependency "rdoc"
89
+ end
90
+
91
+ Gem::PackageTask.new(SPEC) do |pkg|
92
+ pkg.need_tar = true
93
+ pkg.need_zip = true
94
+ end
95
+
96
+ task :default => [:build, :test]
@@ -0,0 +1,646 @@
1
+ /*
2
+ * augeas.c: Ruby bindings for augeas
3
+ *
4
+ * Copyright (C) 2008-2011 Red Hat Inc.
5
+ * Copyright (C) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ *
21
+ * Authors: Bryan Kearney <bkearney@redhat.com>
22
+ * Ionuț Arțăriși <iartarisi@suse.cz>
23
+ */
24
+ #include "_augeas.h"
25
+
26
+ #include <ruby.h>
27
+ #include <augeas.h>
28
+
29
+ static VALUE c_augeas;
30
+
31
+ static augeas *aug_handle(VALUE s) {
32
+ augeas *aug;
33
+
34
+ Data_Get_Struct(s, struct augeas, aug);
35
+ if (aug == NULL) {
36
+ rb_raise(rb_eSystemCallError, "Failed to retrieve connection");
37
+ }
38
+ return aug;
39
+ }
40
+
41
+ static void augeas_free(augeas *aug) {
42
+ if (aug != NULL)
43
+ aug_close(aug);
44
+ }
45
+
46
+ /*
47
+ * call-seq:
48
+ * get(PATH) -> String
49
+ *
50
+ * Lookup the value associated with PATH
51
+ */
52
+ VALUE augeas_get(VALUE s, VALUE path) {
53
+ augeas *aug = aug_handle(s);
54
+ const char *cpath = StringValueCStr(path);
55
+ const char *value = NULL;
56
+
57
+ int retval = aug_get(aug, cpath, &value);
58
+
59
+ if (retval == 1 && value != NULL) {
60
+ return rb_str_new(value, strlen(value));
61
+ } else {
62
+ return Qnil;
63
+ }
64
+ }
65
+
66
+ /*
67
+ * call-seq:
68
+ * exists(PATH) -> boolean
69
+ *
70
+ * Return true if there is an entry for this path, false otherwise
71
+ */
72
+ VALUE augeas_exists(VALUE s, VALUE path) {
73
+ augeas *aug = aug_handle(s);
74
+ const char *cpath = StringValueCStr(path);
75
+ int ret = aug_get(aug, cpath, NULL);
76
+
77
+ return (ret == 1) ? Qtrue : Qfalse;
78
+ }
79
+
80
+ /*
81
+ * call-seq:
82
+ * set(PATH, VALUE) -> int
83
+ *
84
+ * Set the value associated with PATH to VALUE. VALUE is copied into the
85
+ * internal data structure. Intermediate entries are created if they don't
86
+ * exist.
87
+ */
88
+ VALUE augeas_set(VALUE s, VALUE path, VALUE value) {
89
+ augeas *aug = aug_handle(s);
90
+ const char *cpath = StringValueCStr(path) ;
91
+ const char *cvalue = StringValueCStrOrNull(value) ;
92
+
93
+ int callValue = aug_set(aug, cpath, cvalue) ;
94
+ return INT2FIX(callValue);
95
+ }
96
+
97
+ /*
98
+ * call-seq:
99
+ * set(PATH, VALUE) -> boolean
100
+ *
101
+ * Set the value associated with PATH to VALUE. VALUE is copied into the
102
+ * internal data structure. Intermediate entries are created if they don't
103
+ * exist.
104
+ */
105
+ VALUE augeas_set_old(VALUE s, VALUE path, VALUE value) {
106
+ augeas *aug = aug_handle(s);
107
+ const char *cpath = StringValueCStr(path) ;
108
+ const char *cvalue = StringValueCStrOrNull(value) ;
109
+
110
+ int callValue = aug_set(aug, cpath, cvalue) ;
111
+ VALUE returnValue ;
112
+
113
+ if (callValue == 0)
114
+ returnValue = Qtrue ;
115
+ else
116
+ returnValue = Qfalse ;
117
+
118
+ return returnValue ;
119
+ }
120
+
121
+ /*
122
+ * call-seq:
123
+ * setm(BASE, SUB, VALUE) -> boolean
124
+ *
125
+ * Set multiple nodes in one operation. Find or create a node matching
126
+ * SUB by interpreting SUB as a path expression relative to each node
127
+ * matching BASE. SUB may be NULL, in which case all the nodes matching
128
+ * BASE will be modified.
129
+ */
130
+ VALUE augeas_setm(VALUE s, VALUE base, VALUE sub, VALUE value) {
131
+ augeas *aug = aug_handle(s);
132
+ const char *cbase = StringValueCStr(base) ;
133
+ const char *csub = StringValueCStrOrNull(sub) ;
134
+ const char *cvalue = StringValueCStrOrNull(value) ;
135
+
136
+ int callValue = aug_setm(aug, cbase, csub, cvalue) ;
137
+ return INT2FIX(callValue);
138
+ }
139
+
140
+ /*
141
+ * call-seq:
142
+ * insert(PATH, LABEL, BEFORE) -> int
143
+ *
144
+ * Make LABEL a sibling of PATH by inserting it directly before or after PATH.
145
+ * The boolean BEFORE determines if LABEL is inserted before or after PATH.
146
+ */
147
+ VALUE augeas_insert(VALUE s, VALUE path, VALUE label, VALUE before) {
148
+ augeas *aug = aug_handle(s);
149
+ const char *cpath = StringValueCStr(path) ;
150
+ const char *clabel = StringValueCStr(label) ;
151
+
152
+ int callValue = aug_insert(aug, cpath, clabel, RTEST(before));
153
+ return INT2FIX(callValue) ;
154
+ }
155
+
156
+ /*
157
+ * call-seq:
158
+ * mv(SRC, DST) -> int
159
+ *
160
+ * Move the node SRC to DST. SRC must match exactly one node in the
161
+ * tree. DST must either match exactly one node in the tree, or may not
162
+ * exist yet. If DST exists already, it and all its descendants are
163
+ * deleted. If DST does not exist yet, it and all its missing ancestors are
164
+ * created.
165
+ */
166
+ VALUE augeas_mv(VALUE s, VALUE src, VALUE dst) {
167
+ augeas *aug = aug_handle(s);
168
+ const char *csrc = StringValueCStr(src);
169
+ const char *cdst = StringValueCStr(dst);
170
+ int r = aug_mv(aug, csrc, cdst);
171
+
172
+ return INT2FIX(r);
173
+ }
174
+
175
+ /*
176
+ * call-seq:
177
+ * rm(PATH) -> int
178
+ *
179
+ * Remove path and all its children. Returns the number of entries removed
180
+ */
181
+ VALUE augeas_rm(VALUE s, VALUE path, VALUE sibling) {
182
+ augeas *aug = aug_handle(s);
183
+ const char *cpath = StringValueCStr(path) ;
184
+
185
+ int callValue = aug_rm(aug, cpath) ;
186
+ return INT2FIX(callValue) ;
187
+ }
188
+
189
+ /*
190
+ * call-seq:
191
+ * match(PATH) -> an_array
192
+ *
193
+ * Return all the paths that match the path expression PATH as an aray of
194
+ * strings.
195
+ * Returns an empty array if no paths were found.
196
+ */
197
+ VALUE augeas_match(VALUE s, VALUE p) {
198
+ augeas *aug = aug_handle(s);
199
+ const char *path = StringValueCStr(p);
200
+ char **matches = NULL;
201
+ int cnt, i;
202
+
203
+ cnt = aug_match(aug, path, &matches) ;
204
+ if (cnt < 0)
205
+ return -1;
206
+
207
+ VALUE result = rb_ary_new();
208
+ for (i = 0; i < cnt; i++) {
209
+ rb_ary_push(result, rb_str_new(matches[i], strlen(matches[i])));
210
+ free(matches[i]) ;
211
+ }
212
+ free (matches) ;
213
+
214
+ return result ;
215
+ }
216
+
217
+ /*
218
+ * call-seq:
219
+ * match(PATH) -> an_array
220
+ *
221
+ * Return all the paths that match the path expression PATH as an aray of
222
+ * strings.
223
+ * Raises an error if no paths were found.
224
+ */
225
+ VALUE augeas_match_old(VALUE s, VALUE p) {
226
+ augeas *aug = aug_handle(s);
227
+ const char *path = StringValueCStr(p);
228
+ char **matches = NULL;
229
+ int cnt, i;
230
+
231
+ cnt = aug_match(aug, path, &matches) ;
232
+ if (cnt < 0)
233
+ rb_raise(rb_eSystemCallError, "Matching path expression '%s' failed",
234
+ path);
235
+
236
+ VALUE result = rb_ary_new();
237
+ for (i = 0; i < cnt; i++) {
238
+ rb_ary_push(result, rb_str_new(matches[i], strlen(matches[i])));
239
+ free(matches[i]) ;
240
+ }
241
+ free (matches) ;
242
+
243
+ return result ;
244
+ }
245
+
246
+ /*
247
+ * call-seq:
248
+ * save() -> int
249
+ *
250
+ * Write all pending changes to disk
251
+ */
252
+ VALUE augeas_save(VALUE s) {
253
+ augeas *aug = aug_handle(s);
254
+ int callValue = aug_save(aug);
255
+ return INT2FIX(callValue);
256
+ }
257
+
258
+ /*
259
+ * call-seq:
260
+ * save() -> boolean
261
+ *
262
+ * Write all pending changes to disk
263
+ */
264
+ VALUE augeas_save_old(VALUE s) {
265
+ augeas *aug = aug_handle(s);
266
+ int callValue = aug_save(aug) ;
267
+ VALUE returnValue ;
268
+
269
+ if (callValue == 0)
270
+ returnValue = Qtrue ;
271
+ else
272
+ returnValue = Qfalse ;
273
+
274
+ return returnValue ;
275
+ }
276
+
277
+ /*
278
+ * call-seq:
279
+ * load() -> int
280
+ *
281
+ * Load files from disk according to the transforms under +/augeas/load+
282
+ */
283
+ VALUE augeas_load(VALUE s) {
284
+ augeas *aug = aug_handle(s);
285
+ int callValue = aug_load(aug);
286
+ return INT2FIX(callValue);
287
+ }
288
+
289
+ /*
290
+ * call-seq:
291
+ * load() -> boolean
292
+ *
293
+ * Load files from disk according to the transforms under +/augeas/load+
294
+ */
295
+ VALUE augeas_load_old(VALUE s) {
296
+ augeas *aug = aug_handle(s);
297
+ int callValue = aug_load(aug);
298
+ VALUE returnValue ;
299
+
300
+ if (callValue == 0)
301
+ returnValue = Qtrue ;
302
+ else
303
+ returnValue = Qfalse ;
304
+
305
+ return returnValue ;
306
+ }
307
+
308
+ /*
309
+ * call-seq:
310
+ * defvar(NAME, EXPR) -> boolean
311
+ *
312
+ * Define a variable NAME whose value is the result of evaluating EXPR. If
313
+ * a variable NAME already exists, its name will be replaced with the
314
+ * result of evaluating EXPR.
315
+ *
316
+ * If EXPR is NULL, the variable NAME will be removed if it is defined.
317
+ *
318
+ */
319
+ VALUE augeas_defvar(VALUE s, VALUE name, VALUE expr) {
320
+ augeas *aug = aug_handle(s);
321
+ const char *cname = StringValueCStr(name);
322
+ const char *cexpr = StringValueCStrOrNull(expr);
323
+
324
+ int r = aug_defvar(aug, cname, cexpr);
325
+
326
+ return (r < 0) ? Qfalse : Qtrue;
327
+ }
328
+
329
+ /*
330
+ * call-seq:
331
+ * defnode(NAME, EXPR, VALUE) -> boolean
332
+ *
333
+ * Define a variable NAME whose value is the result of evaluating EXPR,
334
+ * which must be non-NULL and evaluate to a nodeset. If a variable NAME
335
+ * already exists, its name will be replaced with the result of evaluating
336
+ * EXPR.
337
+ *
338
+ * If EXPR evaluates to an empty nodeset, a node is created, equivalent to
339
+ * calling AUG_SET(AUG, EXPR, VALUE) and NAME will be the nodeset containing
340
+ * that single node.
341
+ *
342
+ * Returns +false+ if +aug_defnode+ fails, and the number of nodes in the
343
+ * nodeset on success.
344
+ */
345
+ VALUE augeas_defnode(VALUE s, VALUE name, VALUE expr, VALUE value) {
346
+ augeas *aug = aug_handle(s);
347
+ const char *cname = StringValueCStr(name);
348
+ const char *cexpr = StringValueCStrOrNull(expr);
349
+ const char *cvalue = StringValueCStrOrNull(value);
350
+
351
+ /* FIXME: Figure out a way to return created, maybe accept a block
352
+ that gets run when created == 1 ? */
353
+ int r = aug_defnode(aug, cname, cexpr, cvalue, NULL);
354
+
355
+ return (r < 0) ? Qfalse : INT2NUM(r);
356
+ }
357
+
358
+ /* This function returns different names for different augeas API */
359
+ /* version specified in the +version+ argument. See augeas_init_old and */
360
+ /* augeas_init. */
361
+ VALUE augeas_init_split(VALUE m, VALUE r, VALUE l, VALUE f, char version) {
362
+ unsigned int flags = NUM2UINT(f);
363
+ const char *root = StringValueCStrOrNull(r);
364
+ const char *loadpath = StringValueCStrOrNull(l);
365
+ augeas *aug = NULL;
366
+
367
+ aug = aug_init(root, loadpath, flags);
368
+ if (aug == NULL) {
369
+ rb_raise(rb_eSystemCallError, "Failed to initialize Augeas");
370
+ }
371
+ return Data_Wrap_Struct(c_augeas, NULL, augeas_free, aug);
372
+ }
373
+
374
+ VALUE augeas_init_old(VALUE m, VALUE r, VALUE l, VALUE f) {
375
+ return augeas_init_split(m, r, l, f, 0);
376
+ }
377
+ VALUE augeas_init(VALUE m, VALUE r, VALUE l, VALUE f) {
378
+ return augeas_init_split(m, r, l, f, 1);
379
+ }
380
+
381
+
382
+ VALUE augeas_close (VALUE s) {
383
+ augeas *aug = aug_handle(s);
384
+
385
+ aug_close(aug);
386
+ DATA_PTR(s) = NULL;
387
+
388
+ return Qnil;
389
+ }
390
+
391
+ static void hash_set(VALUE hash, const char *sym, VALUE v) {
392
+ rb_hash_aset(hash, ID2SYM(rb_intern(sym)), v);
393
+ }
394
+
395
+ /*
396
+ * call-seq:
397
+ * error -> HASH
398
+ *
399
+ * Retrieve details about the last error encountered and return those
400
+ * details in a HASH with the following entries:
401
+ * - :code error code from +aug_error+
402
+ * - :message error message from +aug_error_message+
403
+ * - :minor minor error message from +aug_minor_error_message+
404
+ * - :details error details from +aug_error_details+
405
+ */
406
+ VALUE augeas_error(VALUE s) {
407
+ augeas *aug = aug_handle(s);
408
+ int code;
409
+ const char *msg = NULL;
410
+ VALUE result;
411
+
412
+ result = rb_hash_new();
413
+
414
+ code = aug_error(aug);
415
+ hash_set(result, "code", INT2NUM(code));
416
+
417
+ msg = aug_error_message(aug);
418
+ if (msg != NULL)
419
+ hash_set(result, "message", rb_str_new2(msg));
420
+
421
+ msg = aug_error_minor_message(aug);
422
+ if (msg != NULL)
423
+ hash_set(result, "minor", rb_str_new2(msg));
424
+
425
+ msg = aug_error_details(aug);
426
+ if (msg != NULL)
427
+ hash_set(result, "details", rb_str_new2(msg));
428
+
429
+ return result;
430
+ }
431
+
432
+ static void hash_set_range(VALUE hash, const char *sym,
433
+ unsigned int start, unsigned int end) {
434
+ VALUE r;
435
+
436
+ r = rb_range_new(INT2NUM(start), INT2NUM(end), 0);
437
+ hash_set(hash, sym, r);
438
+ }
439
+
440
+ VALUE augeas_span(VALUE s, VALUE path) {
441
+ augeas *aug = aug_handle(s);
442
+ char *cpath = StringValueCStr(path);
443
+ char *filename = NULL;
444
+ unsigned int label_start, label_end, value_start, value_end,
445
+ span_start, span_end;
446
+ int r;
447
+ VALUE result;
448
+
449
+ r = aug_span(aug, cpath,
450
+ &filename,
451
+ &label_start, &label_end,
452
+ &value_start, &value_end,
453
+ &span_start, &span_end);
454
+
455
+ result = rb_hash_new();
456
+
457
+ if (r == 0) {
458
+ hash_set(result, "filename", rb_str_new2(filename));
459
+ hash_set_range(result, "label", label_start, label_end);
460
+ hash_set_range(result, "value", value_start, value_end);
461
+ hash_set_range(result, "span", span_start, span_end);
462
+ }
463
+
464
+ free(filename);
465
+
466
+ return result;
467
+ }
468
+
469
+ /*
470
+ * call-seq:
471
+ * srun(COMMANDS) -> [int, String]
472
+ *
473
+ * Run one or more newline-separated commands, returning their output.
474
+ *
475
+ * Returns:
476
+ * an array where the first element is the number of executed commands on
477
+ * success, -1 on failure, and -2 if a 'quit' command was encountered.
478
+ * The second element is a string of the output from all commands.
479
+ */
480
+ VALUE augeas_srun(VALUE s, VALUE text) {
481
+ augeas *aug = aug_handle(s);
482
+ const char *ctext = StringValueCStr(text);
483
+
484
+ struct memstream ms;
485
+ __aug_init_memstream(&ms);
486
+
487
+ int r = aug_srun(aug, ms.stream, ctext);
488
+ __aug_close_memstream(&ms);
489
+
490
+ VALUE result = rb_ary_new();
491
+ rb_ary_push(result, INT2NUM(r));
492
+ rb_ary_push(result, rb_str_new2(ms.buf));
493
+
494
+ free(ms.buf);
495
+ return result;
496
+ }
497
+
498
+ /*
499
+ * call-seq:
500
+ * label(PATH) -> String
501
+ *
502
+ * Lookup the label associated with PATH
503
+ */
504
+ VALUE augeas_label(VALUE s, VALUE path) {
505
+ augeas *aug = aug_handle(s);
506
+ const char *cpath = StringValueCStr(path);
507
+ const char *label = NULL;
508
+
509
+ aug_label(aug, cpath, &label);
510
+ if (label != NULL) {
511
+ return rb_str_new(label, strlen(label)) ;
512
+ } else {
513
+ return Qnil;
514
+ }
515
+ }
516
+
517
+ /*
518
+ * call-seq:
519
+ * rename(SRC, LABEL) -> int
520
+ *
521
+ * Rename the label of all nodes matching SRC to LABEL.
522
+ *
523
+ * Returns +false+ if +aug_rename+ fails, and the number of nodes renamed
524
+ * on success.
525
+ */
526
+ VALUE augeas_rename(VALUE s, VALUE src, VALUE label) {
527
+ augeas *aug = aug_handle(s);
528
+ const char *csrc = StringValueCStr(src);
529
+ const char *clabel = StringValueCStr(label);
530
+ int r = aug_rename(aug, csrc, clabel);
531
+
532
+ return (r < 0) ? Qfalse : INT2NUM(r);
533
+ }
534
+
535
+ /*
536
+ * call-seq:
537
+ * text_store(LENS, NODE, PATH) -> boolean
538
+ *
539
+ * Use the value of node NODE as a string and transform it into a tree
540
+ * using the lens LENS and store it in the tree at PATH, which will be
541
+ * overwritten. PATH and NODE are path expressions.
542
+ */
543
+ VALUE augeas_text_store(VALUE s, VALUE lens, VALUE node, VALUE path) {
544
+ augeas *aug = aug_handle(s);
545
+ const char *clens = StringValueCStr(lens);
546
+ const char *cnode = StringValueCStr(node);
547
+ const char *cpath = StringValueCStr(path);
548
+ int r = aug_text_store(aug, clens, cnode, cpath);
549
+
550
+ return (r < 0) ? Qfalse : Qtrue;
551
+ }
552
+
553
+ /*
554
+ * call-seq:
555
+ * text_retrieve(LENS, NODE_IN, PATH, NODE_OUT) -> boolean
556
+ *
557
+ * Transform the tree at PATH into a string using lens LENS and store it in
558
+ * the node NODE_OUT, assuming the tree was initially generated using the
559
+ * value of node NODE_IN. PATH, NODE_IN, and NODE_OUT are path expressions.
560
+ */
561
+ VALUE augeas_text_retrieve(VALUE s, VALUE lens, VALUE node_in, VALUE path, VALUE node_out) {
562
+ augeas *aug = aug_handle(s);
563
+ const char *clens = StringValueCStr(lens);
564
+ const char *cnode_in = StringValueCStr(node_in);
565
+ const char *cpath = StringValueCStr(path);
566
+ const char *cnode_out = StringValueCStr(node_out);
567
+ int r = aug_text_retrieve(aug, clens, cnode_in, cpath, cnode_out);
568
+
569
+ return (r < 0) ? Qfalse : Qtrue;
570
+ }
571
+
572
+ void Init__augeas() {
573
+ /* Define the NEW ruby class
574
+ *
575
+ * This class is basically the same as the old one, but uses a
576
+ * different naming scheme for methods (prefixing everything with
577
+ * "augeas_"). Also some methods point to different C functions.
578
+ */
579
+ c_augeas = rb_define_class("Augeas", rb_cObject) ;
580
+
581
+ /* Constants for enum aug_flags */
582
+ #define DEF_AUG_FLAG(name) \
583
+ rb_define_const(c_augeas, #name, INT2NUM(AUG_##name))
584
+ DEF_AUG_FLAG(NONE);
585
+ DEF_AUG_FLAG(SAVE_BACKUP);
586
+ DEF_AUG_FLAG(SAVE_NEWFILE);
587
+ DEF_AUG_FLAG(TYPE_CHECK);
588
+ DEF_AUG_FLAG(NO_STDINC);
589
+ DEF_AUG_FLAG(SAVE_NOOP);
590
+ DEF_AUG_FLAG(NO_LOAD);
591
+ DEF_AUG_FLAG(NO_MODL_AUTOLOAD);
592
+ DEF_AUG_FLAG(ENABLE_SPAN);
593
+ #undef DEF_AUG_FLAG
594
+
595
+ /* Constants for enum aug_errcode_t */
596
+ #define DEF_AUG_ERR(name) \
597
+ rb_define_const(c_augeas, #name, INT2NUM(AUG_##name))
598
+ DEF_AUG_ERR(NOERROR);
599
+ DEF_AUG_ERR(ENOMEM);
600
+ DEF_AUG_ERR(EINTERNAL);
601
+ DEF_AUG_ERR(EPATHX);
602
+ DEF_AUG_ERR(ENOMATCH);
603
+ DEF_AUG_ERR(EMMATCH);
604
+ DEF_AUG_ERR(ESYNTAX);
605
+ DEF_AUG_ERR(ENOLENS);
606
+ DEF_AUG_ERR(EMXFM);
607
+ DEF_AUG_ERR(ENOSPAN);
608
+ DEF_AUG_ERR(EMVDESC);
609
+ DEF_AUG_ERR(ECMDRUN);
610
+ DEF_AUG_ERR(EBADARG);
611
+ DEF_AUG_ERR(ELABEL);
612
+ #undef DEF_AUG_ERR
613
+
614
+ /* Define the methods */
615
+ rb_define_singleton_method(c_augeas, "open3", augeas_init, 3);
616
+ rb_define_method(c_augeas, "augeas_defvar", augeas_defvar, 2);
617
+ rb_define_method(c_augeas, "augeas_defnode", augeas_defnode, 3);
618
+ rb_define_method(c_augeas, "augeas_get", augeas_get, 1);
619
+ rb_define_method(c_augeas, "augeas_exists", augeas_exists, 1);
620
+ rb_define_method(c_augeas, "augeas_insert", augeas_insert, 3);
621
+ rb_define_method(c_augeas, "augeas_mv", augeas_mv, 2);
622
+ rb_define_method(c_augeas, "augeas_rm", augeas_rm, 1);
623
+ rb_define_method(c_augeas, "augeas_match", augeas_match, 1);
624
+ rb_define_method(c_augeas, "augeas_save", augeas_save, 0);
625
+ rb_define_method(c_augeas, "augeas_load", augeas_load, 0);
626
+ rb_define_method(c_augeas, "augeas_set", augeas_set, 2);
627
+ rb_define_method(c_augeas, "augeas_setm", augeas_setm, 3);
628
+ /* The `close` and `error` methods as used unchanged in the ruby bindings */
629
+ rb_define_method(c_augeas, "close", augeas_close, 0);
630
+ rb_define_method(c_augeas, "error", augeas_error, 0);
631
+ rb_define_method(c_augeas, "augeas_span", augeas_span, 1);
632
+ rb_define_method(c_augeas, "augeas_srun", augeas_srun, 1);
633
+ rb_define_method(c_augeas, "augeas_label", augeas_label, 1);
634
+ rb_define_method(c_augeas, "augeas_rename", augeas_rename, 2);
635
+ rb_define_method(c_augeas, "augeas_text_store", augeas_text_store, 3);
636
+ rb_define_method(c_augeas, "augeas_text_retrieve", augeas_text_retrieve, 4);
637
+ }
638
+
639
+ /*
640
+ * Local variables:
641
+ * indent-tabs-mode: nil
642
+ * c-indent-level: 4
643
+ * c-basic-offset: 4
644
+ * tab-width: 4
645
+ * End:
646
+ */