Skip to content

refspec: add public parsing api#4519

Merged
pks-t merged 1 commit into
libgit2:masterfrom
cynecx:refspec-parsing
Jun 29, 2018
Merged

refspec: add public parsing api#4519
pks-t merged 1 commit into
libgit2:masterfrom
cynecx:refspec-parsing

Conversation

@cynecx

@cynecx cynecx commented Feb 7, 2018

Copy link
Copy Markdown
Contributor

This PR adds public apis for parsing refspec strings. This already exists but they are all internal.
I am not sure if tests are required here because I guess that the internal api must have tests already and this PR just adds trivial wrapping. But I am happy to add tests if it's really requested.

Comment thread src/refspec.c Outdated

int git_refspec_parse(git_refspec **refspec, const char *input, int is_fetch) {
git_refspec *new_refspec;
if (refspec == NULL || input == NULL) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That should be an assert.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Comment thread src/refspec.c Outdated

is_fetch = !!is_fetch;
new_refspec = git__malloc(sizeof(git_refspec));
if (new_refspec == NULL) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

GITERR_CHECK_ALLOC is what you want here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Comment thread src/refspec.c Outdated
}

void git_refspec_free(git_refspec *refspec) {
if (refspec == NULL) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd be tempted to say that this test is not needed : git_refspec__free already handles it, and git__free doesn't care about NULL.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Comment thread src/refspec.c Outdated
return -1;
}

is_fetch = !!is_fetch;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd move that inside the git_refspec__parse call.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

@tiennou

tiennou commented Feb 7, 2018

Copy link
Copy Markdown
Contributor

It'd be 😍 if you squashed those commits, too !

@cynecx

cynecx commented Feb 7, 2018

Copy link
Copy Markdown
Contributor Author

@tiennou Done!

@pks-t pks-t left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm a bit on the edge whether that API makes sense to expose. Not saying that it shouldn't, but I still would like to know of a certain use case where it would be handy. I'm especially coming from the angle that we have no functions exposed which make real use of the refspec.

I'd definitly like to see a test, though. While the new function mostly wraps the exisitng git_refspec__parse, it's still 14 lines of new code which are never being exercised.

Comment thread include/git2/refspec.h Outdated
* @param refspec a pointer to hold the refspec handle
* @param input the refspec string
* @param is_fetch is this a refspec for a fetch
* @return 0 if the refspec string could be parsed, 1 otherwise

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

1 otherwise is a bit weird. We always return -1 for errors.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry the function is actually returning -1, but this is obviously a documentation error.

Comment thread src/refspec.c Outdated
memset(refspec, 0x0, sizeof(git_refspec));
}

int git_refspec_parse(git_refspec **refspec, const char *input, int is_fetch) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Well, this is definitly is a bit more than a "simple wrapper", regarding it has 14 lines of code. So it should be worth a test

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

While you're fixing up this PR with @pks-t 's changes, please put this { on a newline to match our code formatting rules. (Thanks!)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah, thanks! I noticed this, but forgot to write a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll push some tests right away.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@pks-t About the tests, would a simple valid/not-valid parsing case be sufficient (testing object creation) and a simple comment that the logic should already be tested in the internal version of the api suffice?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@cynex Should suffice in this case, yes.

Comment thread src/refspec.c Outdated
new_refspec = git__malloc(sizeof(git_refspec));
GITERR_CHECK_ALLOC(new_refspec);

if (!git_refspec__parse(new_refspec, input, is_fetch)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You shouldn't pass is_fetch as, as git_refspe__parse accepts a bool. So instead of moving is_fetch = !!is_fetch into git_refspec__parse, you should have that here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@tiennou mentioned to move that line away. But I can move it back here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry, coding style is always a soft thing and different people have different views :P

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

On another note: you could also just move it into the git_refspec__parse line, without first assigning it to itself.

Comment thread src/refspec.c Outdated
return 0;
}

void git_refspec_free(git_refspec *refspec) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same with this {.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry, didn't noticed that. Should be fixed.

@ethomson

ethomson commented Feb 9, 2018

Copy link
Copy Markdown
Member

I'm a bit on the edge whether that API makes sense to expose. Not saying that it shouldn't, but I still would like to know of a certain use case where it would be handy. I'm especially coming from the angle that we have no functions exposed which make real use of the refspec.

Same. @cynecx, understanding your motivations here would help us get more excited about this. As I'm sure you can imagine, every new API we add is something else that we have to maintain, so we're loathe to add new public API unless it's warranted.

We don't want to just expose API for the sake of completeness. So understanding what you're trying to do (and how this helps you do it) is nice so that we know that we should take on this future maintenance burden in order to help you build your software. 😃

@cynecx

cynecx commented Feb 10, 2018

Copy link
Copy Markdown
Contributor Author

Sorry about the delay.

@pks-t @ethomson Well, I am currently developing a custom git remote handler which accepts a command which accepts a refspec as an argument (and my handler obviously uses libgit2). I was actually aiming for reducing code duplication by reusing parsing code which already exists in libgit2. That's my main motivation here, I am not sure if this will convince you but it would definitely offload some parsing logic, which is always good IMO.

@pks-t pks-t left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for your scenario, makes sense to me. Disregarding the micro-nit about !!is_fetch, which you might fix if you feel like it, the only thing missing now is a test for this. As you proposed, two simple tests exercising a succeeding and failing parse should be sufficient.

Comment thread src/refspec.c Outdated
new_refspec = git__malloc(sizeof(git_refspec));
GITERR_CHECK_ALLOC(new_refspec);

if (!git_refspec__parse(new_refspec, input, is_fetch)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

On another note: you could also just move it into the git_refspec__parse line, without first assigning it to itself.

@cynecx

cynecx commented Jun 17, 2018

Copy link
Copy Markdown
Contributor Author

Sorry about the long delay. I've just rebased the branch and added a small test.

@pks-t pks-t left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No worries about the delay, we're usually not the quickest either ;) There's two small nits about out-parameter sanitization and cl_git_pass/cl_git_fail, which is why I also added some minor style recommendations. You don't necessarily need to address the style issues, but I'd be happy if you did :) I'd also ask you to squash the commits together afterwards, as I expect this to be the last round of reviews.

Thanks for your work!

Comment thread tests/network/refspecs.c Outdated

spec = NULL;

error = git_refspec_parse(&spec, "", 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can get rid of the error for this and all the following invocations, as we're always using cl_git_pass and cl_git_fail to check for errors when the invoked function is conforming to libgit2's error style. So:

cl_git_fail(git_refspec_parse(&spec, "", 0));
cl_git_fail(git_refspec_parse(&spec, ":::", 0));
cl_git_pass(git_refspec_pares(&spec, "HEAD:", 1));

Comment thread src/refspec.c
{
git_refspec *new_refspec;
assert(refspec && input);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd like to make sure that we always sanitize the out parameter. So the first thing this function does should be *refspec = NULL.

Comment thread src/refspec.c Outdated
GITERR_CHECK_ALLOC(new_refspec);

is_fetch = !!is_fetch;
if (git_refspec__parse(new_refspec, input, is_fetch) != 0) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You could just pull the !!is_fetch into this function. So if (git_refspec__parse(new_refspec, input, !!is_fetch) != 0)

Comment thread src/refspec.c Outdated
memset(refspec, 0x0, sizeof(git_refspec));
}

int git_refspec_parse(git_refspec **refspec, const char *input, int is_fetch)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Minor nit that doesn't need addressing: we usually name out-parameters out or similar. In case you rename it to out, you could also just rename new_refspec to refspec.

@cynecx cynecx force-pushed the refspec-parsing branch 2 times, most recently from 6798dfa to 6dede7c Compare June 22, 2018 11:07
@cynecx

cynecx commented Jun 22, 2018

Copy link
Copy Markdown
Contributor Author

I've squashed them and addressed the styling issues :)

Fix typo

Fix some type issues

More fixes

Address requested changes

Add test

Fix naming

Fix condition and tests

Address requested changes

Fix typo
@cynecx cynecx force-pushed the refspec-parsing branch from d1b3260 to 630a673 Compare June 22, 2018 11:19
@cynecx

cynecx commented Jun 26, 2018

Copy link
Copy Markdown
Contributor Author

ping.

@pks-t

pks-t commented Jun 29, 2018

Copy link
Copy Markdown
Member

Kicking CI as it had some spurious failures.

@pks-t pks-t merged commit 7192e26 into libgit2:master Jun 29, 2018
@pks-t

pks-t commented Jun 29, 2018

Copy link
Copy Markdown
Member

Thanks for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants