diff --git a/download.nim b/download.nim index e9750c4..14f7f68 100644 --- a/download.nim +++ b/download.nim @@ -36,12 +36,14 @@ proc doPull(meth: TDownloadMethod, downloadDir: string) = cd downloadDir: doCmd("hg pull") -proc doClone(meth: TDownloadMethod, url, downloadDir: string) = +proc doClone(meth: TDownloadMethod, url, downloadDir: string, branch = "") = + let branchArg = if branch == "": "" else: "-b " & branch & " " case meth of TDownloadMethod.Git: - doCmd("git clone --depth 1 " & url & " " & downloadDir) + # TODO: Get rid of the annoying 'detached HEAD' message somehow? + doCmd("git clone --depth 1 " & branchArg & url & " " & downloadDir) of TDownloadMethod.Hg: - doCmd("hg clone -r tip " & url & " " & downloadDir) + doCmd("hg clone -r tip " & branchArg & url & " " & downloadDir) proc getTagsList(dir: string, meth: TDownloadMethod): seq[string] = cd dir: @@ -65,11 +67,24 @@ proc getTagsList(dir: string, meth: TDownloadMethod): seq[string] = else: result = @[] -proc getVersionList(dir: string, - meth: TDownloadMethod): TTable[TVersion, string] = +proc getTagsListRemote(url: string, meth: TDownloadMethod): seq[string] = + result = @[] + case meth + of TDownloadMethod.Git: + var output = execProcess("git ls-remote --tags " & url) + for i in output.splitLines(): + if i == "": continue + let start = i.find("refs/tags/")+"refs/tags/".len + let tag = i[start .. -1] + if not tag.endswith("^{}"): result.add(tag) + + of TDownloadMethod.Hg: + # http://stackoverflow.com/questions/2039150/show-tags-for-remote-hg-repository + raise newException(EInvalidValue, "Hg doesn't support remote tag querying.") + +proc getVersionList(tags: seq[string]): TTable[TVersion, string] = # Returns: TTable of version -> git tag name result = initTable[TVersion, string]() - let tags = getTagsList(dir, meth) for tag in tags: let i = skipUntil(tag, digits) # skip any chars before the version # TODO: Better checking, tags can have any names. Add warnings and such. @@ -84,34 +99,52 @@ proc getDownloadMethod(meth: string): TDownloadMethod = proc doDownload*(pkg: TPackage, downloadDir: string, verRange: PVersionRange) = let downMethod = pkg.downloadMethod.getDownloadMethod() - echo "Executing ", downMethod, "..." + echo "Downloading ", pkg.name, " using ", downMethod, "..." - if existsDir(downloadDir / getSpecificDir(downMethod)): - doPull(downMethod, downloadDir) - else: + case downMethod + of TDownloadMethod.Git: + # For Git we have to query the repo remotely for its tags. This is + # necessary as cloning with a --depth of 1 removes all tag info. + let versions = getTagsListRemote(pkg.url, downMethod).getVersionList() + if versions.len > 0: + echo("Found tags...") + var latest = findLatest(verRange, versions) + ## Note: HEAD is not used when verRange.kind is verAny. This is + ## intended behaviour, the latest tagged version will be used in this case. + if latest.tag != "": + echo("Cloning latest tagged version: ", latest.tag) + removeDir(downloadDir) + doClone(downMethod, pkg.url, downloadDir, latest.tag) + else: + # If no commits have been tagged on the repo we just clone HEAD. + removeDir(downloadDir) + doClone(downMethod, pkg.url, downloadDir) # Grab HEAD. + if verRange.kind != verAny: + # Make sure that HEAD satisfies the requested version range. + let pkginfo = getPkgInfo(downloadDir) + if pkginfo.version.newVersion notin verRange: + raise newException(EBabel, + "No versions of " & pkg.name & + " exist (this usually means that `git tag` returned nothing)." & + "Git HEAD also does not satisfy version range: " & $verRange) + of TDownloadMethod.Hg: removeDir(downloadDir) doClone(downMethod, pkg.url, downloadDir) + let versions = getTagsList(downloadDir, downMethod).getVersionList() - # TODO: Determine if version is a commit hash, if it is. Move the - # git repo to ``babelDir/pkgs``, then babel can simply checkout - # the correct hash instead of constantly cloning and copying. - # N.B. This may still partly be required, as one lib may require hash A - # whereas another lib requires hash B and they are both required by the - # project you want to build. - let versions = getVersionList(downloadDir, downMethod) - if versions.len > 0: - echo("Found tags...") - var latest = findLatest(verRange, versions) - ## Note: HEAD is not used when verRange.kind is verAny. This is - ## intended behaviour, the latest tagged version will be used in this case. - if latest.tag != "": - echo("Switching to latest tagged version: ", latest.tag) - doCheckout(downMethod, downloadDir, latest.tag) - elif verRange.kind != verAny: - let pkginfo = getPkgInfo(downloadDir) - if pkginfo.version.newVersion notin verRange: - raise newException(EBabel, - "No versions of " & pkg.name & - " exist (this usually means that `git tag` returned nothing)." & - "Git HEAD also does not satisfy version range: " & $verRange) - # We use GIT HEAD if it satisfies our ver range + if versions.len > 0: + echo("Found tags...") + var latest = findLatest(verRange, versions) + ## Note: HEAD is not used when verRange.kind is verAny. This is + ## intended behaviour, the latest tagged version will be used in this case. + if latest.tag != "": + echo("Switching to latest tagged version: ", latest.tag) + doCheckout(downMethod, downloadDir, latest.tag) + elif verRange.kind != verAny: + let pkginfo = getPkgInfo(downloadDir) + if pkginfo.version.newVersion notin verRange: + raise newException(EBabel, + "No versions of " & pkg.name & + " exist (this usually means that `git tag` returned nothing)." & + "Git HEAD also does not satisfy version range: " & $verRange) + # We use GIT HEAD if it satisfies our ver range