augeas 0.6.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/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
+ */