Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Rugged::Config#add #834

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,32 @@ repo.config['user.name'] = true
repo.config.delete('user.name')
```

#### Targeting a specific config file

You can also target a specific config file to perform the same actions
as above.

```ruby
# Target a specific git-config file
config = Rugged::Config.new "absolute/path/to/file"

# Read values from the above file
repo.config['core.bare']
```

#### Working with multiple values

Rugged also makes it easy to work with configurations that have multiple values
for the same key (`multivar`s).

```ruby
# Read all values for the 'remote.origin.fetch' key
repo.config.get_all('remote.origin.fetch')

# Add a new value to the 'remote.origin.fetch' key
repo.config.add('remote.origin.fetch', '+refs/pull/*:refs/prs/*')
```

---

### General methods
Expand Down
48 changes: 48 additions & 0 deletions ext/rugged/rugged_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,53 @@ static VALUE rb_git_config_store(VALUE self, VALUE rb_key, VALUE rb_val)
return Qnil;
}

/*
* call-seq:
* cfg.add(key, value)
*
* Store the given +value+ in the Config file, under the section
* and name specified by +key+, without replacing any existing
* entries. Value can be any of the following Ruby types:
* +String+, +true+, +false+ and +Fixnum+.
*
* The config file will be automatically stored to disk.
*
* cfg.add('custom.multi.value', 'fix')
* cfg.add('custom.multi.value', true)
* cfg.add('custom.multi.value', 90)
*/
static VALUE rb_git_config_add(VALUE self, VALUE rb_key, VALUE rb_val)
{
git_config *config;
const char *key;
int error;

Data_Get_Struct(self, git_config, config);
Check_Type(rb_key, T_STRING);

key = StringValueCStr(rb_key);

/*
* "$^" is an unmatchable regexp: it will not match anything at all, so
* all values will be considered new and will not replace any present value.
*/
if (RB_TYPE_P(rb_val, T_STRING)) {
error = git_config_set_multivar(config, key, "$^", StringValueCStr(rb_val));
} else if (RB_TYPE_P(rb_val, T_TRUE) || RB_TYPE_P(rb_val, T_FALSE)) {
error = git_config_set_multivar(config, key, "$^", (rb_val == Qtrue) ? "true" : "false");
} else if (FIXNUM_P(rb_val)) {
char str_value[32];
Copy link
Author

@codenamev codenamev Mar 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took this snippet from the libgit2 source. I'm not entirely sure this is the best way to do this conversion, but I figured I'd at least mimic the behavior. There are some performance enhancements related to windows systems for snprintf that were not ported over (because I have no idea how that works).

snprintf(str_value, sizeof(str_value), "%" PRId64, (int64_t)FIX2INT(rb_val));
error = git_config_set_multivar(config, key, "$^", str_value);
} else {
rb_raise(rb_eTypeError,
"Invalid value; config files can only store string, bool or int keys");
}

rugged_exception_check(error);
return Qnil;
}

/*
* call-seq:
* cfg.delete(key) -> true or false
Expand Down Expand Up @@ -415,6 +462,7 @@ void Init_rugged_config(void)

rb_define_method(rb_cRuggedConfig, "store", rb_git_config_store, 2);
rb_define_method(rb_cRuggedConfig, "[]=", rb_git_config_store, 2);
rb_define_method(rb_cRuggedConfig, "add", rb_git_config_add, 2);

rb_define_method(rb_cRuggedConfig, "get", rb_git_config_get, 1);
rb_define_method(rb_cRuggedConfig, "[]", rb_git_config_get, 1);
Expand Down
16 changes: 16 additions & 0 deletions test/config_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ def test_write_config_values
assert_match(/value = my value/, content)
end

def test_write_multivar_config_values
config = @repo.config
config.add('custom.multivalue', 'my value')
config.add('custom.multivalue', true)
config.add('custom.multivalue', 42)

config2 = @repo.config
custom_multivar = ['my value', 'true', '42']
assert_equal custom_multivar, config2.get_all('custom.multivalue')

content = File.read(File.join(@repo.path, 'config'))
assert_match(/multivalue = my value/, content)
assert_match(/multivalue = true/, content)
assert_match(/multivalue = 42/, content)
end

def test_delete_config_values
config = @repo.config
config.delete('core.bare')
Expand Down
26 changes: 26 additions & 0 deletions test/fixtures/text_file.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,32 @@ repo.config['user.name'] = true
repo.config.delete('user.name')
```

#### Targeting a specific config file

You can also target a specific config file to perform the same actions
as above.

```ruby
# Target a specific git-config file
config = Rugged::Config.new "absolute/path/to/file"

# Read values from the above file
repo.config['core.bare']
```

#### Working with multiple values

Rugged also makes it easy to work with configurations that have multiple values
for the same key (`multivar`s).

```ruby
# Read all values for the 'remote.origin.fetch' key
repo.config.get_all('remote.origin.fetch')

# Add a new value to the 'remote.origin.fetch' key
repo.config.add('remote.origin.fetch', '+refs/pull/*:refs/prs/*')
```

---

### General methods
Expand Down