Skip to content

[Submodule] Git submodule dup #5890

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

Merged
merged 8 commits into from
Jul 22, 2021
Merged

Conversation

lolgear
Copy link
Contributor

@lolgear lolgear commented May 16, 2021

@lolgear lolgear changed the title [Submodule] Git submodule dup. [Submodule] Git submodule dup May 16, 2021
Copy link
Contributor

@neithernut neithernut left a comment

Choose a reason for hiding this comment

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

Disclaimer: not a maintainer.

src/submodule.c Outdated
git_submodule* git_submodule_dup(git_submodule *sm)
{
if (!sm)
return;
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess you meant to return either sm or, explicitly, NULL?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, which one is more appropriate (in current codebase)?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that would be NULL.

Copy link
Member

Choose a reason for hiding this comment

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

I would emulate the existing dup functions like git_commit_dup and return an int and use an out parameter. This way we can change the implementation later in case we add some failure case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ethomson

Should I just use git_object_dup function?

int git_submodule_dup(git_submodule **out, git_submodule *source) {
  return git_object_dup((git_object **)out, (git_object *)source);
}

@lolgear lolgear requested a review from ethomson May 22, 2021 16:57
src/submodule.c Outdated
@@ -1854,6 +1854,11 @@ static void submodule_release(git_submodule *sm)
git__free(sm);
}

int git_submodule_dup(git_submodule **out, git_submodule *source)
{
return git_object_dup((git_object **)out, (git_object *)source);
Copy link
Contributor

Choose a reason for hiding this comment

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

That won't work — git_submodule is not a proper subtype/C "subclass" of git_object, so this will actually clobber memory in the underlying structure when incrementing the refcount.

IIRC your previous version (using GIT_REFCOUNT_INC) was correct but the function's prototype wasn't.

Copy link
Contributor Author

@lolgear lolgear May 26, 2021

Choose a reason for hiding this comment

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

I can't figure out how to adjust *out parameter with previous implementation.
Something like this?

int git_submodule_dup(git_submodule **out, git_submodule *source)
{
  if (!out) { return -1; }
  if (!source) { return -1; }
  *out = source;
  GIT_REFCOUNT_INC(*out);
  return 0;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd (personally) go for this :

int git_submodule_dup(git_submodule **out, git_submodule *source)
{
  GIT_ASSERT_ARG(out);

  if (source != NULL)
    GIT_REFCOUNT_INC(source);
  
  *out = source;
  return 0;
}

Assert because allowing a NULL out could open up the API to misuse/programmer error, only incref if source is non-NULL so a NULL "submodule" can pass through, and always copy either an incref-ed source or NULL in out so it's always a known value and not uninitialized memory.

Copy link
Contributor Author

@lolgear lolgear May 26, 2021

Choose a reason for hiding this comment

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

By the way, project has different styles in spaces/tabs and in nullability checks.
Is there any (current) guide to look at?

Copy link
Contributor

Choose a reason for hiding this comment

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

There's docs/coding-style.md, which is supposed to be current and seems to be. I'd maybe add something about the assertion macros (which are new-ish) and when to use them — ideally for "impossible" or "API misuse" conditions.

@lolgear lolgear requested a review from tiennou May 26, 2021 12:34
src/submodule.c Outdated
{
GIT_ASSERT_ARG(out);

if (source != NULL)
Copy link
Contributor

@tiennou tiennou May 26, 2021

Choose a reason for hiding this comment

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

Yeah… if (source) would have been fine here. Sorry, another project of mine has "all conditions must be explicit", so…

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are a lot of occurrences of != NULL in this file. Should I change it to implicit check?

@lolgear lolgear requested a review from tiennou May 26, 2021 19:17
@lolgear
Copy link
Contributor Author

lolgear commented May 31, 2021

Could anybody check this PR?

Copy link
Contributor

@tiennou tiennou left a comment

Choose a reason for hiding this comment

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

Just a few minor docblock tweaks (I skimmed the header initially). A quick test that exercises the new function and check that both submodules work and can be freed separately would be ❤️, just to be sure nothing regresses.

* Create an in-memory copy of a submodule. The copy must be explicitly
* free'd or it will leak.
*
* @param out Pointer to store the copy of the submodule
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @param out Pointer to store the copy of the submodule
* @param out Pointer to store the copy of the submodule. Cannot be NULL.

* free'd or it will leak.
*
* @param out Pointer to store the copy of the submodule
* @param source Original tag to copy
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @param source Original tag to copy
* @param source Original submodule to copy.

@lolgear
Copy link
Contributor Author

lolgear commented Jun 1, 2021

@tiennou
Could you show me an example of this test?
This function is so common that I can't figure out whether I should add test in separate file or add it in one of the existed files.

@tiennou
Copy link
Contributor

tiennou commented Jun 2, 2021

Sure, I'd put it as test_submodule_lookup__can_be_dupped, which would git_submodule_lookup(), dup that, check that one of the "basic" properties work (name/owner/url, IIRC any one of them, as it's just about accessing the underlying storage), then free the first and assert whatever you checked at the beginning is still what we expect. In case anything goes wrong with memory in the future, the test would cause a segfault.

@lolgear
Copy link
Contributor Author

lolgear commented Jun 3, 2021

@tiennou
Could you check latest changes?
I guess that it is done, but I can't run tests.
A lot of errors at "configure" phase.

@lolgear lolgear requested a review from tiennou June 7, 2021 10:48
Copy link
Member

@ethomson ethomson left a comment

Choose a reason for hiding this comment

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

Overall looks great, a few minor suggestions.

src/submodule.c Outdated
Comment on lines 1860 to 1863

if (source != NULL)
GIT_REFCOUNT_INC(source);

Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason source is optional? I would make it required.

Suggested change
if (source != NULL)
GIT_REFCOUNT_INC(source);
GIT_ASSERT_ARG(source);
GIT_REFCOUNT_INC(source);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ethomson
Fixed

* Create an in-memory copy of a submodule. The copy must be explicitly
* free'd or it will leak.
*
* @param out Pointer to store the copy of the submodule. Cannot be NULL.
Copy link
Member

Choose a reason for hiding this comment

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

Our docs generally tell you when a param is optional, instead of when a param is required.

Suggested change
* @param out Pointer to store the copy of the submodule. Cannot be NULL.
* @param out Pointer to store the copy of the submodule.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ethomson
Fixed

git_submodule *sm_duplicate;
const char *oid = "480095882d281ed676fe5b863569520e54a7d5c0";

// Check original
Copy link
Member

Choose a reason for hiding this comment

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

We don't use // comments in this project...

Suggested change
// Check original
/* Check original */

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ethomson
Fixed

cl_assert(git_submodule_ignore(sm) == GIT_SUBMODULE_IGNORE_NONE);
cl_assert(git_submodule_update_strategy(sm) == GIT_SUBMODULE_UPDATE_CHECKOUT);

// Duplicate and free original
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Duplicate and free original
/* Duplicate and free original */

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ethomson
Fixed

cl_assert(git_submodule_dup(&sm_duplicate, sm) == 0);
git_submodule_free(sm);

// Check duplicate
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Check duplicate
/* Check duplicate */

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ethomson
Fixed

@lolgear lolgear requested a review from ethomson June 15, 2021 14:34
@lolgear
Copy link
Contributor Author

lolgear commented Jun 15, 2021

@ethomson Fixed.

@ethomson
Copy link
Member

Thanks @lolgear!

@ethomson
Copy link
Member

Oops, I didn't hit merge - my bad! Thanks again @lolgear!

@ethomson ethomson merged commit 43b5075 into libgit2:main Jul 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants