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

Tag selector #141

Merged
merged 3 commits into from
Jun 1, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
*.ipr
*.iws

# Eclipse project files
.classpath
.project
.settings/
bin/

# gradle config
.gradle

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pl.allegro.tech.build.axion.release.domain

import pl.allegro.tech.build.axion.release.domain.properties.TagProperties
import pl.allegro.tech.build.axion.release.domain.scm.ScmPosition
import pl.allegro.tech.build.axion.release.domain.scm.ScmRepository;

class TagNameSerializationConfig {

Expand All @@ -20,10 +21,16 @@ class TagNameSerializationConfig {
Closure deserialize = TagNameSerializer.DEFAULT.deserializer

Closure initialVersion = defaultInitialVersion()

Closure tagSelector = defaultTagSelector()

private static Closure defaultInitialVersion() {
return { TagProperties rules, ScmPosition position ->
return '0.1.0'
}
}

private static Closure defaultTagSelector() {
return ScmRepository.LAST_TAG_SELECTOR
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import pl.allegro.tech.build.axion.release.domain.scm.ScmPosition
import pl.allegro.tech.build.axion.release.domain.scm.ScmRepository

class VersionResolver {

private final ScmRepository repository

private final VersionFactory versionFactory

VersionResolver(ScmRepository repository, VersionFactory versionFactory) {
this.repository = repository
this.versionFactory = versionFactory
}

VersionWithPosition resolveVersion(VersionProperties versionRules, TagProperties tagRules, NextVersionProperties nextVersionRules) {
Map positions = readPositions(tagRules, nextVersionRules)

Expand All @@ -29,27 +29,27 @@ class VersionResolver {
if(positions.currentPosition.nextVersionTag) {
position = position.asNotOnTagPosition()
}

return new VersionWithPosition(currentVersion, previousVersion, position)
}


private Map readPositions(TagProperties tagRules, NextVersionProperties nextVersionRules) {
ScmPosition currentPosition = repository.currentPosition(~/^${tagRules.prefix}.*(|${nextVersionRules.suffix})$/)
ScmPosition currentPosition = repository.currentPosition(~/^${tagRules.prefix}.*(|${nextVersionRules.suffix})$/, tagRules.tagSelector)
ScmPositionContext currentPositionContext = new ScmPositionContext(currentPosition, nextVersionRules)

ScmPosition lastReleasePosition
if(currentPositionContext.nextVersionTag) {
lastReleasePosition = repository.currentPosition(~/^${tagRules.prefix}.*/, ~/.*${nextVersionRules.suffix}$/).asOnTagPosition()
lastReleasePosition = repository.currentPosition(~/^${tagRules.prefix}.*/, ~/.*${nextVersionRules.suffix}$/, tagRules.tagSelector).asOnTagPosition()
}
else {
lastReleasePosition = currentPosition.asOnTagPosition()
}

return [
currentPosition: currentPositionContext,
lastReleasePosition: new ScmPositionContext(lastReleasePosition, nextVersionRules)
]
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ class TagProperties {

final Closure<String> initialVersion

final Closure<String> tagSelector

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ package pl.allegro.tech.build.axion.release.domain.scm

import java.util.regex.Pattern

import groovy.lang.Closure;

interface ScmRepository {
public static final Closure<String> LAST_TAG_SELECTOR = { List<String> tags ->
tags && tags.size() > 0 ? tags[-1] : null
}

void fetchTags(ScmIdentity identity, String remoteName)

Expand All @@ -17,8 +22,10 @@ interface ScmRepository {
String currentBranch()

ScmPosition currentPosition(Pattern tagPattern)

ScmPosition currentPosition(Pattern tagPattern, Pattern inversePattern)

ScmPosition currentPosition(Pattern tagPattern, Closure<String> tagSelector)

ScmPosition currentPosition(Pattern tagPattern, Pattern inversePattern, Closure<String> tagSelector)

boolean remoteAttached(String remoteName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import pl.allegro.tech.build.axion.release.domain.scm.ScmRepository
import java.util.regex.Pattern

class DryRepository implements ScmRepository {

private static final ReleaseLogger logger = ReleaseLogger.Factory.logger(DryRepository)

private final ScmRepository delegateRepository
Expand Down Expand Up @@ -50,15 +50,20 @@ class DryRepository implements ScmRepository {
}

@Override
ScmPosition currentPosition(Pattern tagPattern, Pattern inversePattern) {
return currentPosition(tagPattern)
ScmPosition currentPosition(Pattern tagPattern, Closure<String> tagSelector) {
ScmPosition position = delegateRepository.currentPosition(tagPattern, tagSelector)
log("scm position: $position")
return position
}


@Override
ScmPosition currentPosition(Pattern tagPattern, Pattern inversePattern, Closure<String> tagSelector) {
return currentPosition(tagPattern, tagSelector)
}

@Override
ScmPosition currentPosition(Pattern tagPattern) {
ScmPosition position = delegateRepository.currentPosition(tagPattern)
log("scm position: $position")
return position
return currentPosition(tagPattern, LAST_TAG_SELECTOR)
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class DummyRepository implements ScmRepository {

DummyRepository() {
}

private void log(String commandName) {
logger.quiet("Couldn't perform $commandName command on uninitialized repository")
}
Expand Down Expand Up @@ -54,9 +54,14 @@ class DummyRepository implements ScmRepository {
logger.quiet("Could not resolve current position on uninitialized repository, returning default")
return ScmPosition.defaultPosition()
}


@Override
ScmPosition currentPosition(Pattern tagPattern, Closure tagSelector) {
return currentPosition(tagPattern)
}

@Override
ScmPosition currentPosition(Pattern tagPattern, Pattern inversePattern) {
ScmPosition currentPosition(Pattern tagPattern, Pattern inversePattern, Closure tagSelector) {
return currentPosition(tagPattern)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class TagPropertiesFactory {
versionSeparator: config.versionSeparator,
serialize: config.serialize,
deserialize: config.deserialize,
initialVersion: config.initialVersion
initialVersion: config.initialVersion,
tagSelector: config.tagSelector
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ class GitRepository implements ScmRepository {
private static final String GIT_TAG_PREFIX = 'refs/tags/'

private final TransportConfigFactory transportConfigFactory = new TransportConfigFactory()

private final File repositoryDir

private final Grgit repository

private final ScmProperties properties
Expand Down Expand Up @@ -159,38 +159,50 @@ class GitRepository implements ScmRepository {

@Override
ScmPosition currentPosition(Pattern pattern) {
return currentPosition(pattern, Pattern.compile('$a^'))
return currentPosition(pattern, Pattern.compile('$a^'), LAST_TAG_SELECTOR)
}

@Override
ScmPosition currentPosition(Pattern pattern, Pattern inversePattern) {
ScmPosition currentPosition(Pattern pattern, Closure<String> tagSelector) {
return currentPosition(pattern, Pattern.compile('$a^'), tagSelector)
}

@Override
ScmPosition currentPosition(Pattern pattern, Pattern inversePattern, Closure<String> tagSelector) {
if(!hasCommits()) {
return ScmPosition.defaultPosition()
}

Map tags = repository.tag.list()
.grep({ def tag = it.fullName.substring(GIT_TAG_PREFIX.length()); tag ==~ pattern && !(tag ==~ inversePattern) })
.inject([:], { map, entry -> map[entry.commit.id] = entry.fullName.substring(GIT_TAG_PREFIX.length()); return map; })
.inject([:], { map, entry ->
if (map[entry.commit.id] == null) {
map[entry.commit.id] = [] as List<String>
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Dealing with non existing values of map can be simplified by using [:].withDefault {p -> []}

Copy link
Contributor Author

@levsa levsa May 25, 2016

Choose a reason for hiding this comment

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

I looked for something similar, but didn't find one, thanks!

That would break the null-check later on though, but it can be changed to a simple conditional if (map[id]) break;

map[entry.commit.id] << entry.fullName.substring(GIT_TAG_PREFIX.length())
return map
})

ObjectId headId = repository.repository.jgit.repository.resolve(Constants.HEAD)
String branch = repository.branch.current.name

RevWalk walk = new RevWalk(repository.repository.jgit.repository)
walk.sort(RevSort.TOPO)
walk.sort(RevSort.COMMIT_TIME_DESC, true)
RevCommit head = walk.parseCommit(headId)

String tagName = null
List<String> tagNameList = null

walk.markStart(head)
RevCommit commit
for (commit = walk.next(); commit != null; commit = walk.next()) {
tagName = tags[commit.id.name()]
if (tagName != null) {
tagNameList = tags[commit.id.name()]
if (tagNameList != null) {
break
}
}
walk.dispose()

String tagName = tagSelector(tagNameList)
boolean onTag = (commit == null) ? null : commit.id.name() == headId.name()
return new ScmPosition(branch, tagName, onTag, checkUncommittedChanges())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pl.allegro.tech.build.axion.release.domain.properties

import pl.allegro.tech.build.axion.release.domain.TagNameSerializer
import pl.allegro.tech.build.axion.release.domain.scm.ScmRepository;

class TagPropertiesBuilder {

Expand All @@ -17,7 +18,8 @@ class TagPropertiesBuilder {
deserialize: TagNameSerializer.DEFAULT.deserializer,
prefix: 'release',
versionSeparator: '-',
initialVersion: { r, p -> '0.1.0' }
initialVersion: { r, p -> '0.1.0' },
tagSelector: ScmRepository.LAST_TAG_SELECTOR
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class DryRepositoryTest extends Specification {
def "should return currentPosition from real scm"() {
given:
ScmPosition expectedPosition = new ScmPosition("master", "latest", true)
scm.currentPosition(_) >> expectedPosition
scm.currentPosition(_, _) >> expectedPosition

when:
ScmPosition currentPosition = dryRepository.currentPosition(~/^release.*/)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class GitRepositoryTest extends Specification {
void setup() {
Project remoteProject = ProjectBuilder.builder().build()
remoteRawRepository = GitProjectBuilder.gitProject(remoteProject).withInitialCommit().build()[Grgit]

project = ProjectBuilder.builder().build()
Map repositories = GitProjectBuilder.gitProject(project, remoteProject).build()

rawRepository = repositories[Grgit]
repository = repositories[GitRepository]
}
Expand Down Expand Up @@ -111,10 +111,30 @@ class GitRepositoryTest extends Specification {
!position.onTag
}

def "should use the given closure to select one of multiple tags on the same commit"() {
given:
repository.tag('release-1.0.0-rc1')
repository.commit(['*'], "commit after release")
repository.tag('release-1.0.0-rc2')
repository.tag('release-1.0.0')

Closure<String> tagSelector = { tags ->
assert tags == ['release-1.0.0', 'release-1.0.0-rc2']
return 'release-1.0.0'
}

when:
ScmPosition position = repository.currentPosition(~/^release.*/, tagSelector)

then:
position.latestTag == 'release-1.0.0'
position.onTag
}

def "should return default position when no commit in repository"() {
given:
GitRepository commitlessRepository = GitProjectBuilder.gitProject(ProjectBuilder.builder().build()).build()[GitRepository]

when:
ScmPosition position = commitlessRepository.currentPosition(~/^release.*/)

Expand Down Expand Up @@ -215,7 +235,7 @@ class GitRepositoryTest extends Specification {
def "should not push commits if the pushTagsOnly flag is set to true"() {
repository.tag('release-push')
repository.commit(['*'], 'commit after release-push')

when:
repository.push(ScmIdentity.defaultIdentity(), new ScmPushOptions(remote: 'origin', pushTagsOnly: true))

Expand Down