From dbee620accaa48fcdb8579231df9b34294517e11 Mon Sep 17 00:00:00 2001 From: Constantine Plotnikov Date: Wed, 15 Oct 2008 20:11:32 +0400 Subject: [PATCH] git4idea: added commit author support --- .../src/git4idea/changes/ChangeCollector.java | 5 +- .../checkin/GitCheckinEnvironment.java | 143 ++++++++++++++++-- .../src/git4idea/config/GitVcsSettings.java | 25 +++ .../src/git4idea/i18n/GitBundle.properties | 6 +- .../org/jetbrains/git4idea/ssh/SSHMain.java | 2 +- 5 files changed, 168 insertions(+), 13 deletions(-) diff --git a/plugins/git4idea/src/git4idea/changes/ChangeCollector.java b/plugins/git4idea/src/git4idea/changes/ChangeCollector.java index d75b10986381..2c4862c3fa83 100644 --- a/plugins/git4idea/src/git4idea/changes/ChangeCollector.java +++ b/plugins/git4idea/src/git4idea/changes/ChangeCollector.java @@ -125,8 +125,8 @@ class ChangeCollector { GitSimpleHandler handler = new GitSimpleHandler(myProject, myVcsRoot, "diff"); handler.addParameters("--name-status", "--diff-filter=ADMRUX", "-M", "HEAD"); handler.setNoSSH(true); - handler.endOptions(); handler.setSilent(true); + handler.endOptions(); try { String output = handler.run(); String[] lines = output.split("\n"); @@ -166,6 +166,7 @@ class ChangeCollector { // prepare handler GitSimpleHandler handler = new GitSimpleHandler(myProject, myVcsRoot, "ls-files"); handler.addParameters("-v", "--others", "--unmerged"); + handler.setSilent(true); handler.setNoSSH(true); // run handler and collect changes String list = handler.run(); @@ -173,7 +174,7 @@ class ChangeCollector { if (line.length() == 0) { continue; } - String[] tokens = line.split("\t| "); + String[] tokens = line.split("[\t ]+"); String file = GitUtil.unescapePath(tokens[tokens.length - 1]); if ("?".equals(tokens[0])) { myUnversioned.add(myVcsRoot.findFileByRelativePath(file)); diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java index c840606fd5a8..88065a6e9ab3 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java @@ -32,13 +32,17 @@ import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitUtil; import git4idea.commands.GitSimpleHandler; +import git4idea.config.GitVcsSettings; import git4idea.i18n.GitBundle; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; +import java.awt.*; import java.io.*; import java.util.*; +import java.util.List; /** * Git environment for commit operations. @@ -51,7 +55,20 @@ public class GitCheckinEnvironment implements CheckinEnvironment { /** * The project */ - private Project myProject; + private final Project myProject; + /** + * The project + */ + private final GitVcsSettings mySettings; + + /** + * The author for the next commit + */ + private String myNextCommitAuthor = null; + /** + * The push option of the next commit + */ + private Boolean myNextCommitIsPushed = null; /** * Dirty scope manager for the project */ @@ -71,10 +88,14 @@ public class GitCheckinEnvironment implements CheckinEnvironment { * * @param project a project * @param dirtyScopeManager a dirty scope manager + * @param settings */ - public GitCheckinEnvironment(@NotNull Project project, @NotNull final VcsDirtyScopeManager dirtyScopeManager) { + public GitCheckinEnvironment(@NotNull Project project, + @NotNull final VcsDirtyScopeManager dirtyScopeManager, + final GitVcsSettings settings) { myProject = project; myDirtyScopeManager = dirtyScopeManager; + mySettings = settings; } /** @@ -90,7 +111,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment { */ @Nullable public RefreshableOnComponent createAdditionalOptionsPanel(CheckinProjectPanel panel) { - return null; + return new GitCheckinOptions(); } /** @@ -146,7 +167,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment { } try { if (updateIndex(myProject, root, files, exceptions)) { - commit(myProject, root, files, messageFile).run(); + commit(myProject, root, files, messageFile, myNextCommitAuthor).run(); } } catch (VcsException e) { @@ -264,15 +285,23 @@ public class GitCheckinEnvironment implements CheckinEnvironment { /** * Prepare delete files handler. * - * @param project the project - * @param root a vcs root - * @param files a files to commit - * @param message a message file to use + * @param project the project + * @param root a vcs root + * @param files a files to commit + * @param message a message file to use + * @param nextCommitAuthor * @return a simple handler that does the task */ - public static GitSimpleHandler commit(Project project, VirtualFile root, Collection files, File message) { + public static GitSimpleHandler commit(Project project, + VirtualFile root, + Collection files, + File message, + final String nextCommitAuthor) { GitSimpleHandler handler = new GitSimpleHandler(project, root, "commit"); handler.addParameters("--only", "-F", message.getAbsolutePath()); + if (nextCommitAuthor != null) { + handler.addParameters("--author=" + nextCommitAuthor); + } handler.endOptions(); handler.addRelativePaths(files); handler.setNoSSH(true); @@ -335,4 +364,100 @@ public class GitCheckinEnvironment implements CheckinEnvironment { // Otherwise it is not possible to detect moves. myDirtyScopeManager.dirDirtyRecursively(root); } + + /** + * Checkin options for git + */ + private class GitCheckinOptions implements RefreshableOnComponent { + /** + * A container panel + */ + private JPanel myPanel; + /** + * If checked, the changes are pushed to the server as well as connected. + */ + private JCheckBox myPushChanges; + /** + * The author ComboBox, the dropdown contains previously selected authors. + */ + private JComboBox myAuthor; + + /** + * A constructor + */ + GitCheckinOptions() { + myPanel = new JPanel(new GridBagLayout()); + final Insets insets = new Insets(2, 2, 2, 2); + GridBagConstraints c = new GridBagConstraints(); + c.gridx = 0; + c.gridy = 0; + c.anchor = GridBagConstraints.WEST; + c.insets = insets; + myPushChanges = new JCheckBox(GitBundle.message("commit.push.changes")); + myPushChanges.setToolTipText(GitBundle.getString("commit.push.changes.tooltip")); + // do not add checkbox until push implemented + // myPanel.add(myPushChanges, c); + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.WEST; + c.insets = insets; + c.gridx = 0; + c.gridy = 1; + final JLabel authorLabel = new JLabel(GitBundle.message("commit.author")); + myPanel.add(authorLabel, c); + c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.insets = insets; + c.gridx = 0; + c.gridy = 2; + c.weightx = 1; + c.fill = GridBagConstraints.HORIZONTAL; + myAuthor = new JComboBox(mySettings.PREVIOUS_COMMIT_AUTHORS); + myAuthor.addItem(""); + myAuthor.setSelectedItem(""); + myAuthor.setEditable(true); + authorLabel.setLabelFor(myAuthor); + myAuthor.setToolTipText(GitBundle.getString("commit.author.tooltip")); + myPanel.add(myAuthor, c); + } + + /** + * {@inheritDoc} + */ + public JComponent getComponent() { + return myPanel; + } + + /** + * {@inheritDoc} + */ + public void refresh() { + myAuthor.setSelectedItem(""); + myPushChanges.setSelected(false); + myNextCommitAuthor = null; + myNextCommitIsPushed = null; + } + + /** + * {@inheritDoc} + */ + public void saveState() { + String author = (String)myAuthor.getSelectedItem(); + myNextCommitAuthor = author.length() == 0 ? null : author; + if (author.length() == 0) { + myNextCommitAuthor = null; + } + else { + myNextCommitAuthor = author; + mySettings.saveCommitAuthor(author); + } + myNextCommitIsPushed = myPushChanges.isSelected(); + } + + /** + * {@inheritDoc} + */ + public void restoreState() { + refresh(); + } + } } diff --git a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java index 0fe7cfe4e660..e1b7b05ae0be 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java @@ -29,6 +29,8 @@ import com.intellij.util.xmlb.XmlSerializerUtil; import org.jetbrains.annotations.NonNls; import java.io.File; +import java.util.Arrays; +import java.util.LinkedList; /** * Git VCS settings @@ -60,6 +62,29 @@ public class GitVcsSettings implements PersistentStateComponent * The default executable for GIT */ public String GIT_EXECUTABLE = defaultGit(); + /** + * The previously entered authors of the commit (up to 10) + */ + public String[] PREVIOUS_COMMIT_AUTHORS = {}; + /** + * Limit for previous commit authors + */ + private static int PREVIOUS_COMMIT_AUTHORS_LIMIT = 16; + + /** + * Save an author of the commit and make it the first one. If amount of authors exceeds the limit, remove least recently selected author. + * + * @param author an author to save + */ + public void saveCommitAuthor(String author) { + LinkedList authors = new LinkedList(Arrays.asList(PREVIOUS_COMMIT_AUTHORS)); + authors.remove(author); + while (authors.size() >= PREVIOUS_COMMIT_AUTHORS_LIMIT) { + authors.removeLast(); + } + authors.addFirst(author); + PREVIOUS_COMMIT_AUTHORS = authors.toArray(new String[authors.size()]); + } /** * {@inheritDoc} diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties index 757dd8ba01cc..fe4c348fdb84 100644 --- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties +++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties @@ -25,6 +25,10 @@ clone.url.is.not.directory.error=Repository URL is not a directory. cloning.repository=Cloning source repository {0} command.cancelled=The command was cancelled. commit.action.name=Commit +commit.author.tooltip=Specify a commit author here if it is different from committer. The author should be in the format: Author Name <author@ema.il> +commit.author=&Author: +commit.push.changes.tooltip=When this option is enabled, changes are pushed to the server after commit. +commit.push.changes=&Push Changes computing.annotation=Computing annotation for {0} current.branch.action.name=CurrentBranch current.branch.message=Checked out branch: {0} @@ -54,6 +58,7 @@ index.file.error=Updating file in the index failed merge.action.name=Merge merge.branch.message=Select branch to merge into this one ({0}) merge.branch.title=Merge Branch +merge.is.not.needed=Merge is not needed for the file {0} merge.load.files=Loading files for merge merge.tool.action.name=MergeTool merging.branch=Merging branch {0} @@ -108,4 +113,3 @@ vfs.listener.add.title=Add files to Git vfs.listener.delete.single.prompt=Do you want to delete the following file from Git?\n{0}\n\nIf you say NO, you can still delete it later manually. vfs.listener.delete.single.title=Delete file from Git vfs.listener.delete.title=Delete files from Git -merge.is.not.needed=Merge is not needed for the file {0} diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java index 0957419db89f..ca7392223045 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java @@ -530,7 +530,7 @@ public class SSHMain { isNew = false; break; default: - throw new IllegalStateException("Unknow verification result: " + result); + throw new IllegalStateException("Unknown verification result: " + result); } String fingerprint = KnownHosts.createHexFingerprint(serverHostKeyAlgorithm, serverHostKey); boolean keyCheck = myXmlRpcClient.verifyServerHostKey(myHandlerNo, hostname, port, serverHostKeyAlgorithm, fingerprint, isNew);