Skip to content

Commit

Permalink
#2 - Provide command to list all issue branches alongside their state…
Browse files Browse the repository at this point in the history
… in the issue tracker
  • Loading branch information
mp911de authored and odrotbohm committed Feb 15, 2016
1 parent 8abad13 commit 67e5b36
Show file tree
Hide file tree
Showing 24 changed files with 768 additions and 36 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ target/
.factorypath
.springBeans
application-local.properties
spring-shell.log
spring-shell.log
.idea/
*.iml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
*/
@EqualsAndHashCode
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
class Branch {
public class Branch implements Comparable<Branch> {

public static final Branch MASTER = new Branch("master");

Expand Down Expand Up @@ -73,12 +73,17 @@ public boolean isMasterBranch() {
return MASTER.equals(this);
}

/*
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return name;
}

@Override
public int compareTo(Branch o) {
return name.compareToIgnoreCase(o.name);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.release.git;

import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import lombok.EqualsAndHashCode;

import org.springframework.data.release.model.ArtifactVersion;
import org.springframework.data.release.model.ModuleIteration;
import org.springframework.util.Assert;

/**
* Value object to represent a collection of {@link Branch}es.
*
* @author Mark Paluch
*/
@EqualsAndHashCode
public class Branches implements Iterable<Branch> {

private final List<Branch> branches;

/**
* Creates a new {@link Branches} instance for the given {@link List} of {@link Branch}es.
*
* @param source must not be {@literal null}.
*/
Branches(List<Branch> source) {

Assert.notNull(source, "Tags must not be null!");

this.branches = source.stream().//
sorted().collect(Collectors.toList());
}


/**
* Returns all {@link Branch}es as {@link List}.
*
* @return
*/
public List<Branch> asList() {
return branches;
}

/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<Branch> iterator() {
return branches.iterator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,29 @@
*/
package org.springframework.data.release.git;

import lombok.RequiredArgsConstructor;
import java.util.Optional;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.release.CliComponent;
import org.springframework.data.release.jira.Ticket;
import org.springframework.data.release.jira.TicketBranches;
import org.springframework.data.release.model.Project;
import org.springframework.data.release.model.ReleaseTrains;
import org.springframework.data.release.model.Train;
import org.springframework.data.release.model.TrainIteration;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.shell.support.table.Table;
import org.springframework.shell.support.table.TableHeader;
import org.springframework.util.StringUtils;

import lombok.RequiredArgsConstructor;

/**
* @author Oliver Gierke
*/
Expand Down Expand Up @@ -67,8 +73,8 @@ public String tags(@CliOption(key = { "project" }, mandatory = true) String proj

/**
* Resets all projects contained in the given {@link Train}.
*
* @param trainName
*
* @param iteration
* @throws Exception
*/
@CliCommand("git reset")
Expand All @@ -84,7 +90,7 @@ public void prepare(@CliOption(key = "", mandatory = true) TrainIteration iterat
/**
* Pushes all changes of all modules of the given {@link TrainIteration} to the remote server. If {@code tags} is
* given, only the tags are pushed.
*
*
* @param iteration
* @param tags
* @throws Exception
Expand Down Expand Up @@ -118,4 +124,44 @@ public void backportChangelogs(@CliOption(key = "", mandatory = true) TrainItera

git.backportChangelogs(iteration, targets);
}

/**
* List the branches with their tickets of the git repository.
*
* @param projectName
* @return
* @throws Exception
*/
@CliCommand("git issuebranches")
public Table issuebranches(@CliOption(key = { "" }, mandatory = true) String projectName,
@CliOption(key = "resolved") Boolean resolved) throws Exception {

Project project = ReleaseTrains.getProjectByName(projectName);

Table table = new Table();
TicketBranches ticketBranches = git.listTicketBranches(project);

table.addHeader(1, new TableHeader("Branch"));
table.addHeader(2, new TableHeader("Status"));
table.addHeader(3, new TableHeader("Description"));

ticketBranches.stream().sorted().//
filter(branch -> {
Optional<Ticket> ticket = ticketBranches.getTicket(branch);
if (resolved != null && resolved) {
if (!ticket.isPresent() || (ticket.isPresent() && ticket.get().getTicketStatus().isResolved())) {
return false;
}
}

return true;
}).//
forEachOrdered(branch -> {
Optional<Ticket> ticket = ticketBranches.getTicket(branch);
table.addRow(branch.toString(), ticket.map(t -> t.getTicketStatus().getLabel()).orElse(""),
ticket.map(t -> t.getSummary()).orElse(""));
});

return table;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,26 @@
*/
package org.springframework.data.release.git;

import lombok.RequiredArgsConstructor;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import lombok.RequiredArgsConstructor;

import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
Expand All @@ -40,6 +47,7 @@
import org.springframework.data.release.io.Workspace;
import org.springframework.data.release.jira.IssueTracker;
import org.springframework.data.release.jira.Ticket;
import org.springframework.data.release.jira.TicketBranches;
import org.springframework.data.release.model.ArtifactVersion;
import org.springframework.data.release.model.ModuleIteration;
import org.springframework.data.release.model.Project;
Expand Down Expand Up @@ -93,7 +101,7 @@ public void reset(TrainIteration train) {

/**
* Checks out all projects of the given {@link TrainIteration}.
*
*
* @param train
* @throws Exception
*/
Expand Down Expand Up @@ -269,6 +277,63 @@ public VersionTags getTags(Project project) {
});
}

/**
* Retrieve a list of remote branches where their related ticket is resolved.
*
* @param project
* @return
*/
public TicketBranches listTicketBranches(Project project) {

IssueTracker tracker = issueTracker.getPluginFor(project);

try (Git git = new Git(getRepository(project))) {
update(project);
Pattern pattern = Pattern.compile(project.getTracker().getTicketPattern());

Collection<Ref> branches = git.lsRemote().setHeads(true).setTags(false).call();

Set<String> possibleTicketIds = branches.stream().//
filter(branch -> pattern.matcher(branch.getName()).find()).//
map(branch -> {
Matcher matcher = pattern.matcher(branch.getName());
matcher.find();
return matcher.group(1);
}).//
collect(Collectors.toSet());

Collection<Ticket> tickets = tracker.findTickets(project, possibleTicketIds);
Map<String, Ticket> ticketMap = tickets.stream().collect(Collectors.toMap(Ticket::getId, ticket -> ticket));

Map<Branch, Ticket> ticketBranches = new HashMap<>();
branches.stream().//
map(branch -> {
if (branch.getName().startsWith(Constants.R_HEADS)) {
return branch.getName().substring(Constants.R_HEADS.length());
}

if (branch.getName().startsWith(Constants.R_REMOTES)) {
return branch.getName().substring(Constants.R_REMOTES.length());
}
return branch.getName();
}).filter(branchName -> {
Matcher matcher = pattern.matcher(branchName);
return matcher.find();
}).//
forEach((branchName) -> {

Matcher matcher = pattern.matcher(branchName);
matcher.find();
String ticketId = matcher.group(1);
ticketBranches.put(Branch.from(branchName), ticketMap.get(ticketId));
});

return TicketBranches.from(ticketBranches);
} catch (Exception o_O) {
throw new RuntimeException(o_O);
}
}

public void tagRelease(TrainIteration iteration) {

ExecutionUtils.run(iteration, module -> {
Expand Down Expand Up @@ -300,7 +365,7 @@ public void tagRelease(TrainIteration iteration) {
/**
* Commits all changes currently made to all modules of the given {@link TrainIteration}. The summary can contain a
* single {@code %s} placeholder which the version of the current module will get replace into.
*
*
* @param iteration must not be {@literal null}.
* @param summary must not be {@literal null} or empty.
* @throws Exception
Expand Down Expand Up @@ -328,7 +393,7 @@ public void commit(TrainIteration iteration, String summary, Optional<String> de
/**
* Commits the given files for the given {@link ModuleIteration} using the given summary for the commit message. If no
* files are given, all pending changes are committed.
*
*
* @param module must not be {@literal null}.
* @param summary must not be {@literal null} or empty.
* @param files can be empty.
Expand Down Expand Up @@ -505,7 +570,7 @@ private Branch createMaintenanceBranch(ModuleIteration module) {
* starting with the release ticket identifier, followed by a dash separated by spaces and the key word
* {@code Release}. To prevent skimming through the entire Git history, we expect such a commit to be found within the
* 50 most recent commits.
*
*
* @param module
* @return
* @throws Exception
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class GitHubIssue {

private String number;
private String title;
private String state;

public String getId() {
return "#".concat(number);
Expand Down

0 comments on commit 67e5b36

Please sign in to comment.