diff --git a/source/dub/internal/git.d b/source/dub/internal/git.d index d1e52d6..d7e169f 100644 --- a/source/dub/internal/git.d +++ b/source/dub/internal/git.d @@ -65,9 +65,6 @@ // by invoking the "git" executable private string determineVersionWithGitTool(NativePath path) { - import dub.semver; - import std.algorithm : canFind; - import std.conv : to; import std.process; auto git_dir = path ~ ".git"; @@ -81,17 +78,9 @@ return null; } - auto tag = exec("git", git_dir_param, "describe", "--long", "--tags"); - if (tag !is null) { - auto parts = tag.split("-"); - auto commit = parts[$-1]; - auto num = parts[$-2].to!int; - tag = parts[0 .. $-2].join("-"); - if (tag.startsWith("v") && isValidVersion(tag[1 .. $])) { - if (num == 0) return tag[1 .. $]; - else if (tag.canFind("+")) return format("%s.commit.%s.%s", tag[1 .. $], num, commit); - else return format("%s+commit.%s.%s", tag[1 .. $], num, commit); - } + if (const describeOutput = exec("git", git_dir_param, "describe", "--long", "--tags")) { + if (const ver = determineVersionFromGitDescribe(describeOutput)) + return ver; } auto branch = exec("git", git_dir_param, "rev-parse", "--abbrev-ref", "HEAD"); @@ -102,6 +91,49 @@ return null; } +private string determineVersionFromGitDescribe(string describeOutput) +{ + import dub.semver : isValidVersion; + import std.conv : to; + + const parts = describeOutput.split("-"); + const commit = parts[$-1]; + const num = parts[$-2].to!int; + const tag = parts[0 .. $-2].join("-"); + if (tag.startsWith("v") && isValidVersion(tag[1 .. $])) { + if (num == 0) return tag[1 .. $]; + const i = tag.indexOf('+'); + auto r = format("%s%scommit.%s.%s", tag[1 .. (i < 0) ? $ : i], + parts.length > 3 ? "." : "-", num, commit); + if (i > 0) r ~= tag[i .. $]; + return r; + } + return null; +} + +unittest { + // tag v1.0.0 + assert(determineVersionFromGitDescribe("v1.0.0-0-deadbeef") == "1.0.0"); + // 1 commit after v1.0.0 + assert(determineVersionFromGitDescribe("v1.0.0-1-deadbeef") == "1.0.0-commit.1.deadbeef"); + // tag v1.0.0+2.0.0 + assert(determineVersionFromGitDescribe("v1.0.0+2.0.0-0-deadbeef") == "1.0.0+2.0.0"); + // 12 commits after tag v1.0.0+2.0.0 + assert(determineVersionFromGitDescribe("v1.0.0+2.0.0-12-deadbeef") == "1.0.0-commit.12.deadbeef+2.0.0"); + // tag v1.0.0-beta.1 + assert(determineVersionFromGitDescribe("v1.0.0-beta.1-0-deadbeef") == "1.0.0-beta.1"); + // 2 commits after tag v1.0.0-beta.1 + assert(determineVersionFromGitDescribe("v1.0.0-beta.1-2-deadbeef") == "1.0.0-beta.1.commit.2.deadbeef"); + // tag v1.0.0-beta.2+2.0.0 + assert(determineVersionFromGitDescribe("v1.0.0-beta.2+2.0.0-0-deadbeef") == "1.0.0-beta.2+2.0.0"); + // 3 commits after tag v1.0.0-beta.2+2.0.0 + assert(determineVersionFromGitDescribe("v1.0.0-beta.2+2.0.0-3-deadbeef") == "1.0.0-beta.2.commit.3.deadbeef+2.0.0"); + + // invalid tags + assert(determineVersionFromGitDescribe("1.0.0-0-deadbeef") is null); + assert(determineVersionFromGitDescribe("v1.0-0-deadbeef") is null); +} + /** Clones a repository into a new directory. Params: