merge 2.0.0

This commit is contained in:
Eduard Heimbuch
2019-10-17 08:34:23 +02:00
632 changed files with 159635 additions and 65454 deletions

View File

@@ -38,6 +38,7 @@ import com.google.common.base.Strings;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
@@ -217,7 +218,8 @@ class AbstractGitCommand
Optional<RevCommit> doCommit(String message, Person author) {
Person authorToUse = determineAuthor(author);
try {
if (!clone.status().call().isClean()) {
Status status = clone.status().call();
if (!status.isClean() || isInMerge()) {
return of(clone.commit()
.setAuthor(authorToUse.getName(), authorToUse.getMail())
.setMessage(message)
@@ -225,11 +227,15 @@ class AbstractGitCommand
} else {
return empty();
}
} catch (GitAPIException e) {
} catch (GitAPIException | IOException e) {
throw new InternalRepositoryException(context.getRepository(), "could not commit changes", e);
}
}
private boolean isInMerge() throws IOException {
return clone.getRepository().readMergeHeads() != null && !clone.getRepository().readMergeHeads().isEmpty();
}
void push() {
try {
clone.push().call();

View File

@@ -1,28 +1,23 @@
//@flow
import React from "react";
import styled from "styled-components";
import type { Repository, Link } from "@scm-manager/ui-types";
import { ButtonAddons, Button } from "@scm-manager/ui-components";
import type { Repository } from "@scm-manager/ui-types";
import CloneInformation from "./CloneInformation";
import type { Link } from "@scm-manager/ui-types";
import injectSheets from "react-jss";
const styles = {
protocols: {
position: "relative"
},
switcher: {
position: "absolute",
top: 0,
right: 0
}
};
const Wrapper = styled.div`
position: relative;
`;
const Switcher = styled(ButtonAddons)`
position: absolute;
top: 0;
right: 0;
`;
type Props = {
repository: Repository,
// context props
classes: Object
}
repository: Repository
};
type State = {
selected?: Link
@@ -43,8 +38,7 @@ function selectHttpOrFirst(repository: Repository) {
return undefined;
}
class ProtocolInformation extends React.Component<Props, State> {
export default class ProtocolInformation extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
@@ -64,19 +58,19 @@ class ProtocolInformation extends React.Component<Props, State> {
let color = null;
const { selected } = this.state;
if ( selected && protocol.name === selected.name ) {
if (selected && protocol.name === selected.name) {
color = "link is-selected";
}
return (
<Button color={ color } action={() => this.selectProtocol(protocol)}>
<Button color={color} action={() => this.selectProtocol(protocol)}>
{name.toUpperCase()}
</Button>
);
};
render() {
const { repository, classes } = this.props;
const { repository } = this.props;
const protocols = repository._links["protocol"];
if (!protocols || protocols.length === 0) {
@@ -84,25 +78,24 @@ class ProtocolInformation extends React.Component<Props, State> {
}
if (protocols.length === 1) {
return <CloneInformation url={protocols[0].href} repository={repository} />;
return (
<CloneInformation url={protocols[0].href} repository={repository} />
);
}
const { selected } = this.state;
let cloneInformation = null;
if (selected) {
cloneInformation = <CloneInformation repository={repository} url={selected.href} />;
cloneInformation = (
<CloneInformation repository={repository} url={selected.href} />
);
}
return (
<div className={classes.protocols}>
<ButtonAddons className={classes.switcher}>
{protocols.map(this.renderProtocolButton)}
</ButtonAddons>
{ cloneInformation }
</div>
<Wrapper>
<Switcher>{protocols.map(this.renderProtocolButton)}</Switcher>
{cloneInformation}
</Wrapper>
);
}
}
export default injectSheets(styles)(ProtocolInformation);

View File

@@ -12,8 +12,9 @@ import RepositoryConfig from "./RepositoryConfig";
// repository
const gitPredicate = (props: Object) => {
return props.repository && props.repository.type === "git";
// @visibleForTesting
export const gitPredicate = (props: Object) => {
return !!(props && props.repository && props.repository.type === "git");
};
binder.bind(

View File

@@ -0,0 +1,16 @@
// @flow
import "@scm-manager/ui-tests/i18n";
import { gitPredicate } from "./index";
describe("test git predicate", () => {
it("should return false", () => {
expect(gitPredicate()).toBe(false);
expect(gitPredicate({})).toBe(false);
expect(gitPredicate({ repository: {} })).toBe(false);
expect(gitPredicate({ repository: { type: "hg" } })).toBe(false);
});
it("should return true", () => {
expect(gitPredicate({ repository: { type: "git" } })).toBe(true);
});
});

View File

@@ -55,5 +55,9 @@
<conditions>
<min-version>${project.parent.version}</min-version>
</conditions>
<resources>
<script>assets/scm-git-plugin.bundle.js</script>
</resources>
</plugin>

View File

@@ -82,6 +82,26 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase {
assertThat(new String(contentOfFileB)).isEqualTo("b\ncontent from branch\n");
}
@Test
public void shouldAllowEmptyMergeCommit() throws IOException, GitAPIException {
GitMergeCommand command = createCommand();
MergeCommandRequest request = new MergeCommandRequest();
request.setTargetBranch("master");
request.setBranchToMerge("empty_merge");
request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det"));
MergeCommandResult mergeCommandResult = command.merge(request);
assertThat(mergeCommandResult.isSuccess()).isTrue();
Repository repository = createContext().open();
Iterable<RevCommit> commits = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call();
RevCommit mergeCommit = commits.iterator().next();
assertThat(mergeCommit.getParentCount()).isEqualTo(2);
assertThat(mergeCommit.getParent(0).name()).isEqualTo("fcd0ef1831e4002ac43ea539f4094334c79ea9ec");
assertThat(mergeCommit.getParent(1).name()).isEqualTo("d81ad6c63d7e2162308d69637b339dedd1d9201c");
}
@Test
public void shouldNotMergeTwice() throws IOException, GitAPIException {
GitMergeCommand command = createCommand();