Skip to content

Commit e4ca303

Browse files
committed
Add Rugged::Config#add
This method allows you to set multiple values for the same key in a particular config, similar to `git config --add "include.path" some/path`. For example, I have a git config with an existing `include.path` value: ``` $ cat ~/src/opensource/rugged/.git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = [email protected]:codenamev/rugged.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [submodule "vendor/libgit2"] active = true url = https://github.com/libgit2/libgit2.git [include] path = /Users/codenamev/.gitconfig.reflow ``` With `Rugged::Config#add` I can set another value for `include.path` without overwriting the existing value: ``` ruby -I lib -rrugged -e'\ config = Rugged::Repository.new("/Users/codenamev/src/opensource/rugged").config; config.add("include.path", "/Users/codenamev/.gitconfig.extras"); p config.get_all("include.path")' ["/Users/codenamev/.gitconfig.reflow", "/Users/codenamev/.gitconfig.extras"] ``` References #725
1 parent 654ff2f commit e4ca303

File tree

4 files changed

+116
-0
lines changed

4 files changed

+116
-0
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,32 @@ repo.config['user.name'] = true
553553
repo.config.delete('user.name')
554554
```
555555

556+
#### Targeting a specific config file
557+
558+
You can also target a specific config file to perform the same actions
559+
as above.
560+
561+
```ruby
562+
# Target a specific git-config file
563+
config = Rugged::Config.new "absolute/path/to/file"
564+
565+
# Read values from the above file
566+
repo.config['core.bare']
567+
```
568+
569+
#### Working with multiple values
570+
571+
Rugged also makes it easy to work with configurations that have multiple values
572+
for the same key (`multivar`s).
573+
574+
```ruby
575+
# Read all values for the 'remote.origin.fetch' key
576+
repo.config.get_all('remote.origin.fetch')
577+
578+
# Add a new value to the 'remote.origin.fetch' key
579+
repo.config.add('remote.origin.fetch', '+refs/pull/*:refs/prs/*')
580+
```
581+
556582
---
557583

558584
### General methods

ext/rugged/rugged_config.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,53 @@ static VALUE rb_git_config_store(VALUE self, VALUE rb_key, VALUE rb_val)
143143
return Qnil;
144144
}
145145

146+
/*
147+
* call-seq:
148+
* cfg.add(key, value)
149+
*
150+
* Store the given +value+ in the Config file, under the section
151+
* and name specified by +key+, without replacing any existing
152+
* entries. Value can be any of the following Ruby types:
153+
* +String+, +true+, +false+ and +Fixnum+.
154+
*
155+
* The config file will be automatically stored to disk.
156+
*
157+
* cfg.add('custom.multi.value', 'fix')
158+
* cfg.add('custom.multi.value', true)
159+
* cfg.add('custom.multi.value', 90)
160+
*/
161+
static VALUE rb_git_config_add(VALUE self, VALUE rb_key, VALUE rb_val)
162+
{
163+
git_config *config;
164+
const char *key;
165+
int error;
166+
167+
Data_Get_Struct(self, git_config, config);
168+
Check_Type(rb_key, T_STRING);
169+
170+
key = StringValueCStr(rb_key);
171+
172+
/*
173+
* "$^" is an unmatchable regexp: it will not match anything at all, so
174+
* all values will be considered new and will not replace any present value.
175+
*/
176+
if (RB_TYPE_P(rb_val, T_STRING)) {
177+
error = git_config_set_multivar(config, key, "$^", StringValueCStr(rb_val));
178+
} else if (RB_TYPE_P(rb_val, T_TRUE) || RB_TYPE_P(rb_val, T_FALSE)) {
179+
error = git_config_set_multivar(config, key, "$^", (rb_val == Qtrue) ? "true" : "false");
180+
} else if (FIXNUM_P(rb_val)) {
181+
char str_value[32];
182+
snprintf(str_value, sizeof(str_value), "%" PRId64, (int64_t)FIX2INT(rb_val));
183+
error = git_config_set_multivar(config, key, "$^", str_value);
184+
} else {
185+
rb_raise(rb_eTypeError,
186+
"Invalid value; config files can only store string, bool or int keys");
187+
}
188+
189+
rugged_exception_check(error);
190+
return Qnil;
191+
}
192+
146193
/*
147194
* call-seq:
148195
* cfg.delete(key) -> true or false
@@ -415,6 +462,7 @@ void Init_rugged_config(void)
415462

416463
rb_define_method(rb_cRuggedConfig, "store", rb_git_config_store, 2);
417464
rb_define_method(rb_cRuggedConfig, "[]=", rb_git_config_store, 2);
465+
rb_define_method(rb_cRuggedConfig, "add", rb_git_config_add, 2);
418466

419467
rb_define_method(rb_cRuggedConfig, "get", rb_git_config_get, 1);
420468
rb_define_method(rb_cRuggedConfig, "[]", rb_git_config_get, 1);

test/config_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,22 @@ def test_write_config_values
8585
assert_match(/value = my value/, content)
8686
end
8787

88+
def test_write_multivar_config_values
89+
config = @repo.config
90+
config.add('custom.multivalue', 'my value')
91+
config.add('custom.multivalue', true)
92+
config.add('custom.multivalue', 42)
93+
94+
config2 = @repo.config
95+
custom_multivar = ['my value', 'true', '42']
96+
assert_equal custom_multivar, config2.get_all('custom.multivalue')
97+
98+
content = File.read(File.join(@repo.path, 'config'))
99+
assert_match(/multivalue = my value/, content)
100+
assert_match(/multivalue = true/, content)
101+
assert_match(/multivalue = 42/, content)
102+
end
103+
88104
def test_delete_config_values
89105
config = @repo.config
90106
config.delete('core.bare')

test/fixtures/text_file.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,32 @@ repo.config['user.name'] = true
418418
repo.config.delete('user.name')
419419
```
420420

421+
#### Targeting a specific config file
422+
423+
You can also target a specific config file to perform the same actions
424+
as above.
425+
426+
```ruby
427+
# Target a specific git-config file
428+
config = Rugged::Config.new "absolute/path/to/file"
429+
430+
# Read values from the above file
431+
repo.config['core.bare']
432+
```
433+
434+
#### Working with multiple values
435+
436+
Rugged also makes it easy to work with configurations that have multiple values
437+
for the same key (`multivar`s).
438+
439+
```ruby
440+
# Read all values for the 'remote.origin.fetch' key
441+
repo.config.get_all('remote.origin.fetch')
442+
443+
# Add a new value to the 'remote.origin.fetch' key
444+
repo.config.add('remote.origin.fetch', '+refs/pull/*:refs/prs/*')
445+
```
446+
421447
---
422448

423449
### General methods

0 commit comments

Comments
 (0)