mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-65721 Git Sign-off
Add a checkbox to the commit dialog which calls `git commit -s` thus adding "Signed-off-by" suffix to the commit message. There was an idea to add a toggle button which wouldn't call "-s", but modify the commit message in place. However it appeared that this process could cause confusion in several cases, e.g.: * user usually signs commits in this project; * he opens the commit dialog, the signature is already there at the end of the previous commit message; * the commit message is selected to ease writing new commit message; * user starts typing, everything gets erased => * should the sign-off suffix be added or not? The button is still toggled, because it is a project wide control. The checkbox is a bit less neat option, but lets avoid such confusions. The state of the checkbox is remembered in Git project settings. Several methods became non-static to avoid passing 3-4 parameters which can be easily retrieved from the class fields.
This commit is contained in:
@@ -39,6 +39,7 @@ import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.GuiUtils;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.FunctionUtil;
|
||||
import com.intellij.util.NullableFunction;
|
||||
@@ -73,6 +74,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
@@ -99,6 +101,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
private boolean myNextCommitAmend; // If true, the next commit is amended
|
||||
private Boolean myNextCommitIsPushed = null; // The push option of the next commit
|
||||
private Date myNextCommitAuthorDate;
|
||||
private boolean myNextCommitSignOff;
|
||||
|
||||
public GitCheckinEnvironment(@NotNull Project project,
|
||||
@NotNull final VcsDirtyScopeManager dirtyScopeManager,
|
||||
@@ -225,7 +228,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
Set<FilePath> files = new HashSet<>();
|
||||
files.addAll(added);
|
||||
files.addAll(removed);
|
||||
commit(myProject, root, files, messageFile, myNextCommitAuthor, myNextCommitAmend, myNextCommitAuthorDate);
|
||||
commit(myProject, root, files, messageFile);
|
||||
}
|
||||
catch (VcsException ex) {
|
||||
PartialOperation partialOperation = isMergeCommit(ex);
|
||||
@@ -259,13 +262,13 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<VcsException> commitWithCaseOnlyRename(@NotNull Project project,
|
||||
@NotNull VirtualFile root,
|
||||
@NotNull Set<Change> caseOnlyRenames,
|
||||
@NotNull Set<FilePath> added,
|
||||
@NotNull Set<FilePath> removed,
|
||||
@NotNull File messageFile,
|
||||
@Nullable String author) {
|
||||
private List<VcsException> commitWithCaseOnlyRename(@NotNull Project project,
|
||||
@NotNull VirtualFile root,
|
||||
@NotNull Set<Change> caseOnlyRenames,
|
||||
@NotNull Set<FilePath> added,
|
||||
@NotNull Set<FilePath> removed,
|
||||
@NotNull File messageFile,
|
||||
@Nullable String author) {
|
||||
String rootPath = root.getPath();
|
||||
LOG.info("Committing case only rename: " + getLogString(rootPath, caseOnlyRenames) + " in " + getShortRepositoryName(project, root));
|
||||
|
||||
@@ -364,13 +367,13 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
* @param partialOperation
|
||||
* @return true if merge commit was successful
|
||||
*/
|
||||
private static boolean mergeCommit(final Project project,
|
||||
final VirtualFile root,
|
||||
final Set<FilePath> added,
|
||||
final Set<FilePath> removed,
|
||||
final File messageFile,
|
||||
final String author,
|
||||
List<VcsException> exceptions, @NotNull final PartialOperation partialOperation) {
|
||||
private boolean mergeCommit(final Project project,
|
||||
final VirtualFile root,
|
||||
final Set<FilePath> added,
|
||||
final Set<FilePath> removed,
|
||||
final File messageFile,
|
||||
final String author,
|
||||
List<VcsException> exceptions, @NotNull final PartialOperation partialOperation) {
|
||||
HashSet<FilePath> realAdded = new HashSet<>();
|
||||
HashSet<FilePath> realRemoved = new HashSet<>();
|
||||
// perform diff
|
||||
@@ -459,16 +462,19 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void commitWithoutPaths(@NotNull Project project,
|
||||
@NotNull VirtualFile root,
|
||||
@NotNull File messageFile,
|
||||
@Nullable String author) throws VcsException {
|
||||
private void commitWithoutPaths(@NotNull Project project,
|
||||
@NotNull VirtualFile root,
|
||||
@NotNull File messageFile,
|
||||
@Nullable String author) throws VcsException {
|
||||
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.COMMIT);
|
||||
handler.setStdoutSuppressed(false);
|
||||
handler.addParameters("-F", messageFile.getAbsolutePath());
|
||||
if (author != null) {
|
||||
handler.addParameters("--author=" + author);
|
||||
}
|
||||
if (myNextCommitSignOff) {
|
||||
handler.addParameters("--signoff");
|
||||
}
|
||||
handler.endOptions();
|
||||
handler.run();
|
||||
}
|
||||
@@ -573,17 +579,15 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
return rc;
|
||||
}
|
||||
|
||||
private static void commit(Project project,
|
||||
VirtualFile root,
|
||||
Collection<FilePath> files,
|
||||
File message,
|
||||
final String nextCommitAuthor,
|
||||
boolean nextCommitAmend, Date nextCommitAuthorDate)
|
||||
private void commit(@NotNull Project project, @NotNull VirtualFile root, @NotNull Collection<FilePath> files, @NotNull File message)
|
||||
throws VcsException {
|
||||
boolean amend = nextCommitAmend;
|
||||
boolean amend = myNextCommitAmend;
|
||||
for (List<String> paths : VcsFileUtil.chunkPaths(root, files)) {
|
||||
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.COMMIT);
|
||||
handler.setStdoutSuppressed(false);
|
||||
if (myNextCommitSignOff) {
|
||||
handler.addParameters("--signoff");
|
||||
}
|
||||
if (amend) {
|
||||
handler.addParameters("--amend");
|
||||
}
|
||||
@@ -591,11 +595,11 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
amend = true;
|
||||
}
|
||||
handler.addParameters("--only", "-F", message.getAbsolutePath());
|
||||
if (nextCommitAuthor != null) {
|
||||
handler.addParameters("--author=" + nextCommitAuthor);
|
||||
if (myNextCommitAuthor != null) {
|
||||
handler.addParameters("--author=" + myNextCommitAuthor);
|
||||
}
|
||||
if (nextCommitAuthorDate != null) {
|
||||
handler.addParameters("--date", COMMIT_DATE_FORMAT.format(nextCommitAuthorDate));
|
||||
if (myNextCommitAuthorDate != null) {
|
||||
handler.addParameters("--date", COMMIT_DATE_FORMAT.format(myNextCommitAuthorDate));
|
||||
}
|
||||
handler.endOptions();
|
||||
handler.addParameters(paths);
|
||||
@@ -695,6 +699,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
@NotNull private final EditorTextField myAuthorField;
|
||||
@Nullable private Date myAuthorDate;
|
||||
@NotNull private AmendComponent myAmendComponent;
|
||||
@NotNull private final JCheckBox mySignOffCheckbox;
|
||||
|
||||
GitCheckinOptions(@NotNull Project project, @NotNull CheckinProjectPanel panel) {
|
||||
myVcs = assertNotNull(GitVcs.getInstance(project));
|
||||
@@ -705,6 +710,8 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
authorLabel.setLabelFor(myAuthorField);
|
||||
|
||||
myAmendComponent = new MyAmendComponent(project, panel);
|
||||
mySignOffCheckbox = new JBCheckBox("Sign-off commit", mySettings.shouldSignOffCommit());
|
||||
mySignOffCheckbox.setMnemonic(KeyEvent.VK_G);
|
||||
|
||||
GridBag gb = new GridBag().
|
||||
setDefaultAnchor(GridBagConstraints.WEST).
|
||||
@@ -712,6 +719,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
myPanel = new JPanel(new GridBagLayout());
|
||||
myPanel.add(authorLabel, gb.nextLine().next());
|
||||
myPanel.add(myAuthorField, gb.next().fillCellHorizontally().weightx(1));
|
||||
myPanel.add(mySignOffCheckbox, gb.nextLine().next().coverLine());
|
||||
myPanel.add(myAmendComponent.getComponent(), gb.nextLine().next().coverLine());
|
||||
}
|
||||
|
||||
@@ -787,6 +795,8 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
}
|
||||
myNextCommitAmend = myAmendComponent.isAmend();
|
||||
myNextCommitAuthorDate = myAuthorDate;
|
||||
mySettings.setSignOffCommit(mySignOffCheckbox.isSelected());
|
||||
myNextCommitSignOff = mySignOffCheckbox.isSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -78,6 +78,7 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings.S
|
||||
public GitResetMode RESET_MODE = null;
|
||||
public boolean FORCE_PUSH_ALLOWED = false;
|
||||
public GitPushTagMode PUSH_TAGS = null;
|
||||
public boolean SIGN_OFF_COMMIT = false;
|
||||
|
||||
@AbstractCollection(surroundWithTag = false)
|
||||
@Tag("push-targets")
|
||||
@@ -241,6 +242,15 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings.S
|
||||
myState.PUSH_TAGS = mode;
|
||||
}
|
||||
|
||||
public boolean shouldSignOffCommit() {
|
||||
return myState.SIGN_OFF_COMMIT;
|
||||
}
|
||||
|
||||
public void setSignOffCommit(boolean state) {
|
||||
myState.SIGN_OFF_COMMIT = state;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides migration from project settings.
|
||||
* This method is to be removed in IDEA 13: it should be moved to {@link GitVcsApplicationSettings}
|
||||
|
||||
Reference in New Issue
Block a user