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

[WIP] Add source.revision #623

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Conversation

Alloyed
Copy link
Contributor

@Alloyed Alloyed commented Oct 6, 2016

Resolves #569.

In hg, this is implemented by passing revision into the clone command (hg clone myrepo --rev myrev).

In git, this is implemented by performing a full clone (git clone myrepo) and then doing git checkout myrev.

Originally I planned to have a special case that compares source.tag and source.revision when both are defined. This would double check the tag's commit-id, but from a security perspective that just moves the trust from the repository host to the rockspec host. Git already supports tag/commit signing with GPG, which are better ways to verify trust.

todo:

  • input validation (revisions should only be full commit/changeset IDs)
  • git optimizations

tests:

  • error on revision in rockspec < 3.0
  • error on revision in unsupported URL type (other schemes don't do this it looks like)
  • simple revision in git
  • simple revision in hg
  • revision + tag
  • revision + branch (with --single-branch this can be special-cased to avoid full clone)
  • revision + tag + branch

Copy link
Member

@hishamhm hishamhm left a comment

Choose a reason for hiding this comment

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

(This is my first time using the new code-review feature in Github, hope I'm doing this right!)

@@ -58,6 +58,7 @@ local rockspec_types = {
dir = string_1,
tag = string_1,
branch = string_1,
revision = string_1,
Copy link
Member

Choose a reason for hiding this comment

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

You should use revision = { _type = "string", _version = "3.0" } here (or you can even create a string_3 variable)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can do this, but I'm wondering where I should be putting my more complex validation. I need to make sure

  1. the URL specifies either a git or hg repo when revision is specified
  2. that revision is a 40-character hex string

I spotted _pattern, which led me to try _pattern = string.rep("%x", 40), and that works, but it has a very silly error message:

Error: Error loading rockspec: /home/kyle/src/luarocks/test/testfiles/invalid_revision-1.0-1.rockspec: Type mismatch on field source.revision: invalid value HEAD does not match '%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x'

@@ -235,6 +235,10 @@ function fetch.load_local_rockspec(filename, quick)
if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end
if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end

if rockspec.source.revision and not deps.format_is_at_least("3.0") then
Copy link
Member

Choose a reason for hiding this comment

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

With the version checking for the revision field in the type checker, you don't need to version-check again here.

@hishamhm
Copy link
Member

hishamhm commented Oct 6, 2016

Yay, thanks for taking on this feature! I added some comments.

@Alloyed
Copy link
Contributor Author

Alloyed commented Oct 8, 2016

Thanks for the review, I'm working on a commit that resolves it and adds a few of the simpler tests right now.

Something else: I noticed that luarocks already calls the "-1" part of a rockspec version a "rockspec revision", so I'm worried about the two getting confused for each other. Wikipedia suggests changeset as a possible alternate name I'd be okay with.

@hishamhm
Copy link
Member

hishamhm commented Oct 11, 2016

  • I think source.revision won't be ambiguous (that's what the table namespacing is for, after all) and is more obvious than "changeset" — every time I saw people asking for this feature they said "I'd like my rockspec to point to a particular revision", not "changeset". (I'm trying to avoid here a situation where we pick a technically correct name that ends up being more cumbersome in regular use, as it happened when we picked "scm" to refer to in-development rocks).
  • Do we need to force all 40 characters in the revision field? A lot more often I see people using much shorter substrings of revisions and that works fine in practice. Again, I'm thinking about convenience here. Those who want the safety of the full hash can still have it. But it's customary for Git-based tools to accept substrings of the hash.
  • As for the error message, how about adding an _expecting field to be used for composing the error message? As in _expecting = "a hexadecimal revision hash"

@Alloyed
Copy link
Contributor Author

Alloyed commented Oct 11, 2016

  1. Understood on the name/typechecking
  2. The CLI tools will allow up to the shortest unique substring, but the issue is that this leads to a potential time-bomb: what if another commit made after the fact shares that substring? If the original commit is still available a rockspec that used to work will break, or if (say, a bad actor) came along and replaced the original git history, you could get a completely different commit.
    If a rockspec is temporary this isn't a big deal, so maybe this is an argument to be more lenient here, and more strict in luarocks.org.

@hishamhm
Copy link
Member

If a rockspec is temporary this isn't a big deal, so maybe this is an argument to be more lenient here, and more strict in luarocks.org.

This is not a big practical problem at luarocks.org because luarocks upload also stores a .src.rock file which contains a copy of the sources. luarocks build uses the .src.rock by default instead of fetching from git.

@mpeterv
Copy link
Contributor

mpeterv commented Oct 12, 2016

luarocks build uses the .src.rock by default instead of fetching from git.

So does luarocks install

@codecov-io
Copy link

codecov-io commented Dec 5, 2016

Current coverage is 87.93% (diff: 100%)

Merging #623 into luarocks-3 will increase coverage by 0.23%

@@           luarocks-3       #623   diff @@
============================================
  Files              66         69     +3   
  Lines            6936       6998    +62   
  Methods             0          0          
  Messages            0          0          
  Branches            0          0          
============================================
+ Hits             6083       6154    +71   
+ Misses            853        844     -9   
  Partials            0          0          

Powered by Codecov. Last update 3df4bd5...b923f22

@Alloyed
Copy link
Contributor Author

Alloyed commented Jan 3, 2017

Something I noticed: right now, if you use luarocks with an http/https/ssh url, luarocks is forced to do a full clone. Do you remember the reasoning behind it? At least on my machine doing a shallow clone works fine for all three types.

Anyways, an in-words description of how cloning works in this PR:

  1. If you don't need a specific revision, you get a shallow clone (git clone --depth=1). this includes normal branches and tags.
  2. If you do need a specific revision, and you specify a branch, you get only the commits on that branch (git clone --single-branch)
  3. If you specify a revision by itself you get the entire repo. (git clone --)

else
-- otherwise, we need a full clone to make sure we fetch all available
-- revisions
depth = "--"
Copy link
Member

Choose a reason for hiding this comment

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

This seems prone to later issues: -- signifies "things after this point are arguments not options".

end
end

local command = {fs.Q(git_cmd), "clone", depth, rockspec.source.url, module}
Copy link
Member

Choose a reason for hiding this comment

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

Do url and module need to be quoted?


local committish = rockspec.source.revision or tag_or_branch
if committish then
if not fs.execute(fs.Q(git_cmd), "checkout", committish) then
Copy link
Member

Choose a reason for hiding this comment

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

Quote commitish (and/or use -- before it)

-- TODO: if revision is specified and so are tag/branch, then validate to
-- make sure tag/branch matches revision
local rev = rockspec.source.revision
rev = rev or rockspec.source.tag
Copy link
Member

Choose a reason for hiding this comment

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

No need to keep assigning, just start the line from or

rev = rev or rockspec.source.branch

if rev then
command = {hg_cmd, "clone", "--rev", rev, url, module}
Copy link
Member

Choose a reason for hiding this comment

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

Why did git_cmd need fs.Q but hg_cmd doesn't?

@hishamhm hishamhm closed this Mar 12, 2018
@hishamhm hishamhm changed the base branch from luarocks-3 to master April 24, 2018 20:13
@hishamhm
Copy link
Member

This was auto-closed by accident when the (now merged) luarocks-3 branch was deleted. Sorry!

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.

Feature request: "revision" field in rockspecs
5 participants