mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
git4idea: Implemeted forced merge/rebase and stash options for update operation
This commit is contained in:
@@ -49,7 +49,27 @@ import java.util.*;
|
||||
* Git utility/helper methods
|
||||
*/
|
||||
public class GitUtil {
|
||||
/**
|
||||
* The logger instance
|
||||
*/
|
||||
private final static Logger LOG = Logger.getInstance("#git4idea.GitUtil");
|
||||
/**
|
||||
* Comparator for virtual files by name
|
||||
*/
|
||||
public static final Comparator<VirtualFile> VIRTUAL_FILE_COMPARATOR = new Comparator<VirtualFile>() {
|
||||
public int compare(final VirtualFile o1, final VirtualFile o2) {
|
||||
if (o1 == null && o2 == null) {
|
||||
return 0;
|
||||
}
|
||||
if (o1 == null) {
|
||||
return -1;
|
||||
}
|
||||
if (o2 == null) {
|
||||
return 1;
|
||||
}
|
||||
return o1.getPresentableUrl().compareTo(o2.getPresentableUrl());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A private constructor to suppress instance creation
|
||||
@@ -269,8 +289,8 @@ public class GitUtil {
|
||||
* @return timestamp as {@link Date} object
|
||||
*/
|
||||
public static Date parseTimestamp(String value) {
|
||||
return new Date(Long.parseLong(value.trim()) * 1000);
|
||||
}
|
||||
return new Date(Long.parseLong(value.trim()) * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get git roots from content roots
|
||||
@@ -629,8 +649,10 @@ public class GitUtil {
|
||||
return getPossibleBase(file, n - 1, path);
|
||||
}
|
||||
|
||||
public static List<CommittedChangeList> getLocalCommittedChanges(final Project project, final VirtualFile root,
|
||||
final Consumer<GitSimpleHandler> parametersSpecifier) throws VcsException {
|
||||
public static List<CommittedChangeList> getLocalCommittedChanges(final Project project,
|
||||
final VirtualFile root,
|
||||
final Consumer<GitSimpleHandler> parametersSpecifier)
|
||||
throws VcsException {
|
||||
final List<CommittedChangeList> rc = new ArrayList<CommittedChangeList>();
|
||||
|
||||
GitSimpleHandler h = new GitSimpleHandler(project, root, GitHandler.LOG);
|
||||
@@ -650,4 +672,23 @@ public class GitUtil {
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast or wrap exception into a vcs exception, errors and runtime exceptions are just thrown throw.
|
||||
*
|
||||
* @param t an exception to throw
|
||||
* @return a wrapped exception
|
||||
*/
|
||||
public static VcsException rethrowVcsException(Throwable t) {
|
||||
if (t instanceof Error) {
|
||||
throw (Error)t;
|
||||
}
|
||||
if (t instanceof RuntimeException) {
|
||||
throw (RuntimeException)t;
|
||||
}
|
||||
if (t instanceof VcsException) {
|
||||
return (VcsException)t;
|
||||
}
|
||||
return new VcsException(t.getMessage(), t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public class GitVcs extends AbstractVcs {
|
||||
myRollbackEnvironment = gitRollbackEnvironment;
|
||||
myRevSelector = new GitRevisionSelector();
|
||||
myConfigurable = new GitVcsConfigurable(mySettings, myProject);
|
||||
myUpdateEnvironment = new GitUpdateEnvironment(myProject);
|
||||
myUpdateEnvironment = new GitUpdateEnvironment(myProject, this, mySettings);
|
||||
myMergeProvider = new GitMergeProvider(myProject);
|
||||
myCommittedChangeListProvider = new GitCommittedChangeListProvider(myProject);
|
||||
myOutgoingChangesProvider = new GitOutgoingChangesProvider(myProject);
|
||||
|
||||
@@ -70,11 +70,7 @@ public abstract class GitRepositoryAction extends AnAction {
|
||||
GitBundle.getString("repository.action.missing.roots.title"));
|
||||
return;
|
||||
}
|
||||
Collections.sort(roots, new Comparator<VirtualFile>() {
|
||||
public int compare(final VirtualFile o1, final VirtualFile o2) {
|
||||
return o1.getPresentableUrl().compareTo(o2.getPresentableUrl());
|
||||
}
|
||||
});
|
||||
Collections.sort(roots, GitUtil.VIRTUAL_FILE_COMPARATOR);
|
||||
// get default root
|
||||
final VirtualFile[] vFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
|
||||
VirtualFile defaultRootVar = null;
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
|
||||
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeListImpl;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitContentRevision;
|
||||
import git4idea.GitRevisionNumber;
|
||||
@@ -35,6 +36,45 @@ public class GitChangeUtils {
|
||||
private GitChangeUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse changes from lines
|
||||
*
|
||||
* @param project the context project
|
||||
* @param root the git root
|
||||
* @return a set of unmerged files
|
||||
* @throws VcsException if the input format does not matches expected format
|
||||
*/
|
||||
public static List<VirtualFile> unmergedFiles(Project project, VirtualFile root) throws VcsException {
|
||||
HashSet<VirtualFile> unmerged = new HashSet<VirtualFile>();
|
||||
String rootPath = root.getPath();
|
||||
GitSimpleHandler h = new GitSimpleHandler(project, root, GitHandler.LS_FILES);
|
||||
h.setNoSSH(true);
|
||||
h.setSilent(true);
|
||||
h.addParameters("--unmerged");
|
||||
LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
for (StringScanner s = new StringScanner(h.run()); s.hasMoreData();) {
|
||||
if (s.isEol()) {
|
||||
s.nextLine();
|
||||
continue;
|
||||
}
|
||||
s.boundedToken('\t');
|
||||
final String relative = s.line();
|
||||
String path = rootPath + "/" + GitUtil.unescapePath(relative);
|
||||
VirtualFile file = lfs.refreshAndFindFileByPath(path);
|
||||
assert file != null : "The unmerged file is not found " + path;
|
||||
file.refresh(false, false);
|
||||
unmerged.add(file);
|
||||
}
|
||||
if(unmerged.size() == 0) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
ArrayList<VirtualFile> rc = new ArrayList<VirtualFile>(unmerged.size());
|
||||
rc.addAll(unmerged);
|
||||
Collections.sort(rc, GitUtil.VIRTUAL_FILE_COMPARATOR);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse changes from lines
|
||||
*
|
||||
@@ -57,7 +97,7 @@ public class GitChangeUtils {
|
||||
StringScanner sc = new StringScanner(s);
|
||||
parseChanges(project, vcsRoot, thisRevision, parentRevision, sc, changes, ignoreNames);
|
||||
if (sc.hasMoreData()) {
|
||||
throw new IllegalStateException("Uknown file status: " + sc.line());
|
||||
throw new IllegalStateException("Unknown file status: " + sc.line());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,14 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings>
|
||||
* IDEA SSH should be used instead of native SSH.
|
||||
*/
|
||||
public SshExecutable SSH_EXECUTABLE = DEFAULT_SSH;
|
||||
/**
|
||||
* True if stash/unstash operation should be performed before update.
|
||||
*/
|
||||
public boolean UPDATE_STASH = true;
|
||||
/**
|
||||
* The type of update operation to perform
|
||||
*/
|
||||
public UpdateType UPDATE_TYPE = UpdateType.BRANCH_DEFAULT;
|
||||
|
||||
/**
|
||||
* Save an author of the commit and make it the first one. If amount of authors exceeds the limit, remove least recently selected author.
|
||||
@@ -200,4 +208,16 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings>
|
||||
* Naive SSH.
|
||||
*/
|
||||
NATIVE_SSH, }
|
||||
|
||||
/**
|
||||
* The type of update to perform
|
||||
*/
|
||||
public enum UpdateType {
|
||||
/** Use default specified in the config file for the branch */
|
||||
BRANCH_DEFAULT,
|
||||
/** Merge fetched commits with local branch */
|
||||
MERGE,
|
||||
/** Rebase local commits upon the fetched branch*/
|
||||
REBASE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,385 +1,401 @@
|
||||
action.text.show.all.submitted=Show all files changed by this commit
|
||||
add.action.name=Add
|
||||
addrefspec.button=Add
|
||||
addrefspec.get.references.tooltip=Get remote tag and branch references (depending on checkbox state).
|
||||
addrefspec.get.references=&Get References
|
||||
addrefspec.getting.references.title=Getting remote references for {0}
|
||||
addrefspec.include.branches.tooltip=The next update references wil retrieve remote branches.
|
||||
addrefspec.include.branches=Include &branches
|
||||
addrefspec.include.tags.tooltip=The next update references wil retrieve remote tags.
|
||||
addrefspec.include.tags=Include &tags
|
||||
addrefspec.node.branches=Branches
|
||||
addrefspec.node.tags=Tags
|
||||
addrefspec.reference.chooser.tooltip=Select remote branch and tag references
|
||||
addrefspec.title=Add Reference(s)
|
||||
annotate.action.name=Annotate
|
||||
annotation.tool.tip=commit {0}\nAuthor: {1}\nDate: {2}\n\n{3}
|
||||
checking.out=Checkout {0}
|
||||
checkout.action.name=Checkout
|
||||
checkout.branch.label=&Checkout
|
||||
checkout.branch.name.exists=Branch with the same name exists. Use override option to force branch creation.
|
||||
checkout.branch=Checkout
|
||||
checkout.create.ref.log.tooltip=If checked the reference log is created for the branch. It allows time based searches. (the option \"-l\")
|
||||
checkout.create.ref.log=Create ref &log
|
||||
checkout.include.tags.tooltip=If checked, the combobox will inclue tags names as well as branches.
|
||||
checkout.include.tags=&Include tags
|
||||
checkout.invalid.new.branch.name=Invalid new branch name
|
||||
checkout.new.branch.tooltip=Enter name of new branch here. Leave blank if you do not want to create a new branch.
|
||||
checkout.new.branch=As &new branch
|
||||
checkout.override.branch=&Override
|
||||
checkout.override.tooltip=If ckecked a branch will be created even if a branch with the same name already exists. The previous branch will be deleted.
|
||||
checkout.ref.tooltip=Select branch, tag, or enter commit reference
|
||||
checkout.retrieving.branches.and.tags=Retrieving branches and tags
|
||||
checkout.track.branch=&Track branch
|
||||
checkout.track.tooltip=If checked, the newly created branch will track original branch during pull.
|
||||
checkout.validate.tooltip=Use this button to validate reference expression if entered manually.
|
||||
checkout.validate=&Validate
|
||||
checkout.validation.failed=Source revision validation failed
|
||||
clone.button=Clone
|
||||
clone.destination.directory.description=Select a parent directory destination directory for clone
|
||||
clone.destination.directory.title=Parent Directory
|
||||
clone.destination.exists.error=The path {0} exists. The Git cannot clone to existing directory.
|
||||
clone.dir.name=Directory &Name
|
||||
clone.invalid.origin=The origin name is in invalid format.
|
||||
clone.invalid.url=Repository URL is a malformed URL or non-existent directory.
|
||||
clone.origin=&Origin Name
|
||||
clone.parent.dir=&Parent Directory
|
||||
clone.parent.missing.error=The parent path {0} must exist.
|
||||
clone.repository.url=Git &Repository URL
|
||||
clone.test.failed.error=Repository test has failed.
|
||||
clone.test.success.message=<html>Connection to repository <tt>{0}</tt> has been successful.</html>
|
||||
clone.test.success=Connection successful
|
||||
clone.test=&Test
|
||||
clone.testing=Testing repository {0}
|
||||
clone.title=Clone Repository
|
||||
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=<html>Specify a commit author here if it is different from committer. The author should be in the format: Author Name <author@ema.il></html>
|
||||
commit.author=&Author:
|
||||
commit.partial.merge.message=<html>The following files are not included in commit.<ul>{0}</ul>Perform commit with all files included?</html>
|
||||
commit.partial.merge.title=Partial Merge Commit
|
||||
commit.push.changes.tooltip=When this option is enabled, changes are pushed to the server after commit.
|
||||
commit.push.changes=&Push Changes
|
||||
common.current.branch.tooltip=The currently checked out branch.
|
||||
common.current.branch=Current Branch:
|
||||
common.git.root.tooltip=Select git vcs root
|
||||
common.git.root=Git &Root:
|
||||
common.no.active.branch=<no active branch>
|
||||
computing.annotation=Computing annotation for {0}
|
||||
current.branch.action.name=CurrentBranch
|
||||
current.branch.change.tracked=Change Tracked Branch
|
||||
current.branch.message=Checked out branch: {0}
|
||||
current.branch.title=Current Branch
|
||||
current.branch.tracked.branch.none=<none>
|
||||
current.branch.tracked.branch.tooltip=Select the branch to track
|
||||
current.branch.tracked.branch=&Branch:
|
||||
current.branch.tracked.remote.none=<none>
|
||||
current.branch.tracked.remote.this=<this repository>
|
||||
current.branch.tracked.repository.tooltip=Select repository to track
|
||||
current.branch.tracked.repository=Re&pository:
|
||||
current.branch.tracked.title=Tracked Branch
|
||||
debug.git.exec=DEBUG: work-dir: [{0}] exec: [{1}]
|
||||
delete.action.name=Delete
|
||||
diff.find.error=Finding revision for diff: {0}
|
||||
error.dialog.title=Error
|
||||
error.list.title={0} Error:
|
||||
error.occurred.during=Error occurred during ''{0}''
|
||||
fetch.action.name=Fetch
|
||||
fetch.button=Fetch
|
||||
fetch.force.references.update.tooltip=Forces update of branch references for which update is not forced in refrence mapping.
|
||||
fetch.force.references.update=Force references &update
|
||||
fetch.remote.label=Re&mote:
|
||||
fetch.remote.tooltip=Remote name or url for fetch
|
||||
fetch.tags.label=Fetch &tags:
|
||||
fetch.tags.policy.all=All
|
||||
fetch.tags.policy.for.fetched.commits=For fetched commits
|
||||
fetch.tags.policy.none=None
|
||||
fetch.tags.tooltip=<html>Select fetched commits policy<ul><li><i>For fetched commits</i> means tags associated with commits on fetched branches are fetched.</li><li><i>All</i> means that all tags and reference commits are fetched</li><li><i>None</i> means that no tags are fetched.</li></ul></html>
|
||||
fetch.title=Git Fetch
|
||||
fetching.tags.title=Updating tags from {0}
|
||||
fetching.title=Fetching from {0}
|
||||
find.git.description=Select path to git executable
|
||||
find.git.error.title=Error Running git
|
||||
find.git.success.title=Git Executed Successfully
|
||||
find.git.title=Git Configuration
|
||||
find.git.unsupported.message=<html><tt>{0}</tt><br>This version is unsupported, and some plugin functionality could fail to work.<br>The minimal supported version is <em>{1}</em>.</html>
|
||||
fix.roots.button=Accept
|
||||
fix.roots.list.tooltip=The suggested list of Git VCS roots, new roots are marked as bold, removed roots are marked as overstriked.
|
||||
fix.roots.message=The following Git vcs roots will be used instead of the current Git VCS roots.
|
||||
fix.roots.title=Fix Git VCS Roots
|
||||
fix.roots.valid.message=The invalid Git roots have been fixed already.
|
||||
fix.roots.valid.title=All Git Roots Are Valid
|
||||
getting.history=Getting history for {0}
|
||||
git.default.commit.message=\n# Brief commit description here\n\n# Full commit description here (comment lines starting with '#' will not be included)\n\n
|
||||
git.error.exit=The git process exited with the code {0}
|
||||
git.running=<html>Running: {0}</html>
|
||||
git.vcs.config.path.label=Path to &git executable:
|
||||
git.vcs.config.ssh.mode.idea=IDEA ssh
|
||||
git.vcs.config.ssh.mode.native=Native
|
||||
git.vcs.config.ssh.mode.tooltip=<html>Specify which version of SSH to be used with git.<ul><li><b>Native</b> means that the native ssh will be used.</li><li><b>IDEA SSH</b> means that the implementation provided by the IDEA will be used.</li></ul>The native implementation might cause hangups on some platforms. In native case, you also might need to configure <em>ssh-askpass</em> for your platform to recieve GUI promopts for passwords.</html>
|
||||
git.vcs.config.ssh.mode=&SSH executable:
|
||||
git.vcs.config.test.label=Test
|
||||
git.vcs.config.test=&Test
|
||||
index.file.error=Updating file in the index failed
|
||||
init.add.root.message=Do you want to add this directory as vcs root?
|
||||
init.add.root.title=Git Init
|
||||
init.destination.directory.description=Select directory where the new Git repository will be created.
|
||||
init.destination.directory.title=Select directory for git init
|
||||
init.error.already.under.git=The selected directory {0} is already under git. The submodules are not yet supported.
|
||||
init.error.title=git init Error
|
||||
merge.action.name=Merge
|
||||
merge.add.log.information.tooltip=Add log information to the commit message (\"--log\" option)
|
||||
merge.add.log.information=Add &log information
|
||||
merge.branch.button=Merge
|
||||
merge.branch.message=Select branch to merge into this one ({0})
|
||||
merge.branch.title=Merge Branches
|
||||
merge.branches.tooltip=<html>The chooser for braches. Select one or more braches to merge (already merged branches are not shown)</html>.
|
||||
merge.branches=&Branches to merge:
|
||||
merge.commit.message.tooltip=The commit message to use in case if merge results in commit (\"-m\" option)
|
||||
merge.commit.message=Commit &Message
|
||||
merge.default.strategy=<default>
|
||||
merge.is.not.needed=Merge is not needed for the file {0}
|
||||
merge.load.files=Loading files for merge
|
||||
merge.no.commit.tooltip=Force no commit for merge (the \"--no-commit\" option)
|
||||
merge.no.commit=No &commit
|
||||
merge.no.fast.forward.tooltip=Disable fast forward (\"--no-ff\" option)
|
||||
merge.no.fast.forward=No &fast forward
|
||||
merge.retrieving.branches=Retrieving unmerged branches
|
||||
merge.squash.commit=S&quash commit
|
||||
merge.squash.tooltip=Squash all changes into the single commit (\"--squash\" option)
|
||||
merge.strategy.tooltip=The merge strategy to use (\"-s\" option)
|
||||
merge.strategy=&Strategy:
|
||||
merge.tool.action.name=MergeTool
|
||||
merge.tool.column.status.deleted=Deleted
|
||||
merge.tool.column.status.modified=Modified
|
||||
merge.tool.column.theirs.status=Theirs
|
||||
merge.tool.column.yours.status=Yours
|
||||
merging.branch=Merging branch {0}
|
||||
merging.title=Merging changes to {0}
|
||||
paths.affected.title=Paths affected in commit {0}
|
||||
pull.action.name=Pull
|
||||
pull.button=Pull
|
||||
pull.force.reference.update=Force reference &update
|
||||
pull.get.branches.tooltip=Get branch names from remote repository. Otherwise a locally cached information is used.
|
||||
pull.get.branches=&Get Branches
|
||||
pull.getting.remote.branches=Getting remote branches
|
||||
pull.remote.tooltip=Registered remote name or URL.
|
||||
pull.remote=Re&mote:
|
||||
pull.retrieving.remotes=Retrieving remotes
|
||||
pull.title=Pull changes
|
||||
pull.url.message=Enter remote repository URL to pull/merge (empty for default):
|
||||
pull.url.title=Pull URL
|
||||
pulling.title=Pulling changes from {0}
|
||||
push.action.name=Push
|
||||
push.branches.tooltip=Select branches to push
|
||||
push.branches=&Branches:
|
||||
push.button=Push
|
||||
push.force.update.tooltip=If selected remote ref is updated even if they are is not an ancestor of the local ref.
|
||||
push.force.update=&Force update
|
||||
push.policy.all=All
|
||||
push.policy.default=Default
|
||||
push.policy.mirror=Mirror
|
||||
push.policy.selected=Selected branches
|
||||
push.policy.tooltip=<html>Select push policy:<ul><li><em>Default</em> - the push is done according to the configuration of the remote.</li><li><em>Selected branches</em> - selected branches are pushed.</li><li><em>All</em> - all references under refs/heads are pushed.</li><li><em>Mirror</em> - all references under refs/ are pushed including tags and remotes.</li></ul></html>
|
||||
push.policy=&Push:
|
||||
push.remote.tooltip=Specify remote repository URL or remote name where to push changes.
|
||||
push.remote=Re&mote:
|
||||
push.show.tags.tooltip=If selected, the tags are shown in branch chooser as well.
|
||||
push.show.tags=Show ta&gs
|
||||
push.tags.tooltip=All tag refereneces are pushed in addition to references specified in references section.
|
||||
push.tags=Push &tags
|
||||
push.title=Push Changes
|
||||
push.use.thin.pack.tooltip=If this option is selected, the push will spend extra CPU cycles to minimize amount of data transferred (use it for slow connections)
|
||||
push.use.thin.pack=&Use thin pack
|
||||
pushing.all.changes=Pushing all commited changes, refs & tags to remote repos
|
||||
rebase.abort.action.name=Abort Rebasing
|
||||
rebase.action.error=Git Rebase Error
|
||||
rebase.action.message=Mulitple git roots have unfinished rebase process, please select root to perform action on.
|
||||
rebase.action.name=Rebase
|
||||
rebase.action.no.root=There is no rebase operation in progress in the project
|
||||
rebase.branch.tooltip=Select branch to rebase (if branch is different from the current branch, it will be checked out first)
|
||||
rebase.branch=&Branch:
|
||||
rebase.button=Rebase
|
||||
rebase.continue.action.name=Continue Rebasing
|
||||
rebase.editor.action.column=Action
|
||||
rebase.editor.button=Start Rebasing
|
||||
rebase.editor.comment.column=Comment
|
||||
rebase.editor.commit.column=Commit
|
||||
rebase.editor.invalid.entryset=No commits found to rebase
|
||||
rebase.editor.invalid.squash=The first non-skip commint could not be marked as squashed since squash merges commit with the previous commit.
|
||||
rebase.editor.message=Reorder and edit &rebased commits
|
||||
rebase.editor.move.down.tooltip=Move commit down (commit will be applied later)
|
||||
rebase.editor.move.down=Move &Down
|
||||
rebase.editor.move.up.tooltip=Move commit up in the list (commit will be applied earlier)
|
||||
rebase.editor.move.up=Move &Up
|
||||
rebase.editor.title=Rebasing commits
|
||||
rebase.editor.view.tooltip=View commit contents
|
||||
rebase.editor.view=&View
|
||||
rebase.from.tooltip=Sepecify actual base for the branch. Leave blank to onto.
|
||||
rebase.from=&From:
|
||||
rebase.in.progress=Interactive rebase has been already started for this git root.
|
||||
rebase.interactive.tooltip=If selected, the interactive rebase will be preformed.
|
||||
rebase.interactive=&Interactive
|
||||
rebase.invalid.from=\"From\" reference expression is invalid.
|
||||
rebase.invalid.onto=\"Onto\" reference expression is invalid.
|
||||
rebase.merge.strategy.tooltip=Select merge strategy to use
|
||||
rebase.merge.strategy=Merge &Strategy:
|
||||
rebase.no.merge.tooltip=If selected, no merge strategies will be applied during the rebase.
|
||||
rebase.no.merge=&Do not use merge strategies
|
||||
rebase.onto.tooltip=The reference that will become a new base for selected branch.
|
||||
rebase.onto.validate=&Validate
|
||||
rebase.onto=&Onto:
|
||||
rebase.preserve.merges.tooltip=Preserve merges during rebease instead of squashing them.
|
||||
rebase.preserve.merges=&Preserve Merges
|
||||
rebase.result.amend.title=Rebase Suspended
|
||||
rebase.result.amend=Stopped for amending commit while rebasing ({0}/{1}).\nAmmed commit and continue the rebase process.
|
||||
rebase.result.cancelled.title=Rebase Cancelled
|
||||
rebase.result.cancelled=The rebase process was cancelled.
|
||||
rebase.result.conflict.title=Rebase Suspended
|
||||
rebase.result.conflict=Stopped rebasing because of conflict ({0}/{1}).\nResolve conflicts and continue the rebase process.
|
||||
rebase.result.error.title=Rebase Error
|
||||
rebase.result.error=Stopped rebasing because of error while rebasing ({0}/{1}).\nCheck vcs console for details.
|
||||
rebase.show.remote.branches.tooltip=If selected, remote branches are shown in drop down as well.
|
||||
rebase.show.remote.branches=Show Re&mote Branches
|
||||
rebase.show.tags.tooltip=Show tags in \"from\" and \"onto\" dropdowns.
|
||||
rebase.skip.action.name=Skip Commit in Rebasing
|
||||
rebase.title=Rebase branch
|
||||
rebase.unstructured.editor.button=Resume Rebasing
|
||||
rebase.unstructured.editor.git.root=Git Root:
|
||||
rebase.unstructured.editor.message=Git rebase operation requested additional &information through the editor:
|
||||
rebase.unstructured.editor.title=Addtional Rebase Input
|
||||
rebase.unstructured.editor.tooltip=Edit this text according to instructions provided inline
|
||||
rebase.valdate.onto.tooltip=Valdate "onto" reference.
|
||||
rebase.validate.from.tooltip=Validate \"from\" reference
|
||||
rebase.validate.from=Va&lidate
|
||||
rebasing.title=Rebasing...
|
||||
refspec.add.all.branches.tooltip=Add refspec that maps all remote branches by glob spec.
|
||||
refspec.add.all.branches=Add A&ll Branches
|
||||
refspec.add.all.tags.tooltip=Adds mapping entry for all tags
|
||||
refspec.add.all.tags=Add All Ta&gs
|
||||
refspec.add.ref.tooltip=Add branch or tag by name
|
||||
refspec.add.ref=&Add...
|
||||
refspec.branch.prefix.tooltip=Specify default branch prefix for the mapping.
|
||||
refspec.branch.prefix=Remote &Name:
|
||||
refspec.column.force=Force
|
||||
refspec.column.local=Local
|
||||
refspec.column.remote=Remote
|
||||
refspec.default.tooltip=Restore default reference mapping
|
||||
refspec.default=&Default
|
||||
refspec.remove.tooltip=Delete refspec entry
|
||||
refspec.remove=Remo&ve
|
||||
refspec.title=Reference mapping
|
||||
refspec.validation.remote.invalid=The invalid local name for remote
|
||||
refspec.validation.remote.is.blank=The local name for remote is blank
|
||||
regase.show.tags=Show &tags
|
||||
repository.action.missing.roots.misconfigured=Neither of configured git roots are is under git. The configured directory or some of its ancestors must have ".git" directory in it.
|
||||
repository.action.missing.roots.title=No git roots
|
||||
repository.action.missing.roots.unconfigured.message=No git roots are configured for the project.
|
||||
reset.action.name=Reset Head ...
|
||||
reset.button=Reset
|
||||
reset.commit.invalid=The specified commit expression did not pass validation.
|
||||
reset.commit.label=To &Commit:
|
||||
reset.commit.tooltip=The commit that will become the current HEAD\n as result of reset operation.
|
||||
reset.title=Reset Head
|
||||
reset.type.hard=Hard
|
||||
reset.type.mixed=Mixed
|
||||
reset.type.soft=Soft
|
||||
reset.type.tooltip=<html>The reset type (see also <code>git reset</code> man page):<ul><li><b>Mixed</b> resets index but not working tree</li><li><b>Soft</b> leaves index and working tree, just moves head pointer</li><li><b>Hard</b> resets index and working tree.<em>Changes in the working tree will be lost</em></li></ul></html>
|
||||
reset.type=Reset &Type:
|
||||
reset.validate.tooltip=Validate the commit pointer and check the content of referenced commit.
|
||||
reset.validate=&Validate
|
||||
resetting.title=Resetting HEAD...
|
||||
revert.action.name=Revert
|
||||
revision.graph=RevisionGraph
|
||||
root.tracker.message=Some configured Git VCS roots are not under Git or have Git repositories in subdirectories without configured VCS root.
|
||||
select.branch.to.checkout=Select branch to checkout
|
||||
show.all.paths.affected.action.name=Show All Affected Paths
|
||||
ssh.ask.passphrase.title=SSH Key Passphrase
|
||||
ssh.askPassphrase.message=Please enter passphrase for the private key {0} (the user name is {1})
|
||||
ssh.changed.host.key=<html>The server host key for the host {0}:{1} has changed to {2} (type {3}).\nDo you want to accept the changed key?</html>
|
||||
ssh.confirm.key.titile=Confirm SSH Server Key
|
||||
ssh.error.title=Authentication error
|
||||
ssh.keyboard.interactive.title=SSH Keyboard Interactive: {0}
|
||||
ssh.keyboard.interactive.username=Username:
|
||||
ssh.new.host.key=<html>Connecting to a new host {0}:{1} that has the key {2} (type {3}).\nDo you want to add this host to known hosts database?</html>
|
||||
ssh.password.message=Please enter password for user {0}
|
||||
ssh.password.title=SSH Password Login
|
||||
sshmain.failed.to.verify.key=Failed to verify key: {0}
|
||||
sshmain.forwarding.failed=Forwarding {0} failed: {1}
|
||||
sshmain.invald.host.key=Invald host key {0} {1}
|
||||
sshmain.invalid.amount.of.arguments=Invalid amount of arguments: {0}
|
||||
sshmain.invalidpassphrase=Invalid passphrase for the key {0}
|
||||
sshmain.keyboard.interactive.failed=Keyboard interactive authentication failed.
|
||||
sshmain.password.failed=Invalid user or password.
|
||||
sshmain.pk.authenitication.failed=Authentication using key {0} failed.
|
||||
sshmain.too.mush.passphrase.guesses=Invalid passphrase for the key {0}({1} attempts)
|
||||
stash.action.name=Stash
|
||||
stash.button=Create Stash
|
||||
stash.keep.index.tooltip=If this checkbox is selected, indexed changes are kept in the index.
|
||||
stash.keep.index=Keep &index
|
||||
stash.message.tooltip=Enter stash message here.
|
||||
stash.message=&Message:
|
||||
stash.title=Stash
|
||||
stashing.title=Stashing changes...
|
||||
tag.action.name=Tag
|
||||
tag.button=Create Tag
|
||||
tag.commit.label=&Commit:
|
||||
tag.commit.tooltip=Enter name of commit or object to tag or leave blank to use HEAD.
|
||||
tag.error.creating.message.file.message=Unable to create message file: {0}
|
||||
tag.error.creating.message.file.title=Error creating message file
|
||||
tag.error.invalid.commit=The commit or object name is invalid.
|
||||
tag.error.tag.exists=The tag with the same name exists.
|
||||
tag.force.tooltip=Force creation of the text even if tag with such name already exists.
|
||||
tag.force=&Force
|
||||
tag.getting.existing.tags=Getting existing tags...
|
||||
tag.message.label=&Message:
|
||||
tag.message.tooltip=If the message is not empty, an annotated tag is created.
|
||||
tag.message=Specify tag name:
|
||||
tag.name.label=Tag &Name:
|
||||
tag.name.tooltip=Enter the new tag name here.
|
||||
tag.nonvcs.error.message=ERROR: Files not tagged, not all are under VCS root!
|
||||
tag.nonvcs.error.title=Tag Result
|
||||
tag.title=Tag
|
||||
tag.validate.tooltip=Click this button to the validate commit to be tagged.
|
||||
tag.validate=&Validate
|
||||
tagging.title=Tagging files...
|
||||
unindexed.files.changlelist.name=Unindexed Files
|
||||
unstash.action.name=UnStash
|
||||
unstash.branch.label\:=As new &branch:
|
||||
unstash.branch.tooltip=If non-empty name is entered, the stash is checked out as a new branch.
|
||||
unstash.button.apply=Apply Stash
|
||||
unstash.button.branch=Branch
|
||||
unstash.button.pop=Pop Stash
|
||||
unstash.clear.tooltip=Delete all stashes in the repository.
|
||||
unstash.clear=&Clear
|
||||
unstash.clearing.stashes=Clearing stashes...
|
||||
unstash.drop.tooltip=Delete selected stash
|
||||
unstash.drop=&Drop
|
||||
unstash.dropping.stash=Dropping stash {0}...
|
||||
unstash.error.branch.exists=The specified branch already exists
|
||||
unstash.error.invalid.branch.name=Invalid branch name
|
||||
unstash.pop.stash.tooltip=If selected the stash is dropped after it is applied.
|
||||
unstash.pop.stash=&Pop stash
|
||||
unstash.reinstate.index.tooltip=Attempt to reinstate index as well as working tree changes.
|
||||
unstash.reinstate.index=Reinstate &index
|
||||
unstash.stashes.item=<html><b><tt>{0}</tt></b>:<i>{1}</i>:{2}</html>
|
||||
unstash.stashes.tooltip=Select a stash to operate for.
|
||||
unstash.stashes=&Stashes:
|
||||
unstash.title=UnStash Changes
|
||||
unstash.view.tooltip=View selected stash
|
||||
unstash.view=&View
|
||||
unstashing.title=UnStashing changes...
|
||||
util.remote.renderer.default=<html><b>{0}</b>(<i>{1}</i>)</html>
|
||||
util.remote.renderer.none=<html><i>None</i></html>
|
||||
util.remote.renderer.normal=<html><b>{0}</b>(<i>{1}</i>)</html>
|
||||
util.remote.renderer.self=<html><i>Current repository</i></html>
|
||||
vcs.unable.to.run.git=Unable to run git: {0} ({1})
|
||||
vcs.unsupported.version=Unsupported version of git configured: {0}. The minimal supported version is {1}
|
||||
vfs.listener.add.single.prompt=Do you want to add the following file to Git?\n{0}\n\nIf you say NO, you can still add it later manually.
|
||||
vfs.listener.add.single.title=Add file to Git
|
||||
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
|
||||
action.text.show.all.submitted=Show all files changed by this commit
|
||||
add.action.name=Add
|
||||
addrefspec.button=Add
|
||||
addrefspec.get.references.tooltip=Get remote tag and branch references (depending on checkbox state).
|
||||
addrefspec.get.references=&Get References
|
||||
addrefspec.getting.references.title=Getting remote references for {0}
|
||||
addrefspec.include.branches.tooltip=The next update references wil retrieve remote branches.
|
||||
addrefspec.include.branches=Include &branches
|
||||
addrefspec.include.tags.tooltip=The next update references wil retrieve remote tags.
|
||||
addrefspec.include.tags=Include &tags
|
||||
addrefspec.node.branches=Branches
|
||||
addrefspec.node.tags=Tags
|
||||
addrefspec.reference.chooser.tooltip=Select remote branch and tag references
|
||||
addrefspec.title=Add Reference(s)
|
||||
annotate.action.name=Annotate
|
||||
annotation.tool.tip=commit {0}\nAuthor: {1}\nDate: {2}\n\n{3}
|
||||
checking.out=Checkout {0}
|
||||
checkout.action.name=Checkout
|
||||
checkout.branch.label=&Checkout
|
||||
checkout.branch.name.exists=Branch with the same name exists. Use override option to force branch creation.
|
||||
checkout.branch=Checkout
|
||||
checkout.create.ref.log.tooltip=If checked the reference log is created for the branch. It allows time based searches. (the option \"-l\")
|
||||
checkout.create.ref.log=Create ref &log
|
||||
checkout.include.tags.tooltip=If checked, the combobox will inclue tags names as well as branches.
|
||||
checkout.include.tags=&Include tags
|
||||
checkout.invalid.new.branch.name=Invalid new branch name
|
||||
checkout.new.branch.tooltip=Enter name of new branch here. Leave blank if you do not want to create a new branch.
|
||||
checkout.new.branch=As &new branch
|
||||
checkout.override.branch=&Override
|
||||
checkout.override.tooltip=If ckecked a branch will be created even if a branch with the same name already exists. The previous branch will be deleted.
|
||||
checkout.ref.tooltip=Select branch, tag, or enter commit reference
|
||||
checkout.retrieving.branches.and.tags=Retrieving branches and tags
|
||||
checkout.track.branch=&Track branch
|
||||
checkout.track.tooltip=If checked, the newly created branch will track original branch during pull.
|
||||
checkout.validate.tooltip=Use this button to validate reference expression if entered manually.
|
||||
checkout.validate=&Validate
|
||||
checkout.validation.failed=Source revision validation failed
|
||||
clone.button=Clone
|
||||
clone.destination.directory.description=Select a parent directory destination directory for clone
|
||||
clone.destination.directory.title=Parent Directory
|
||||
clone.destination.exists.error=The path {0} exists. The Git cannot clone to existing directory.
|
||||
clone.dir.name=Directory &Name
|
||||
clone.invalid.origin=The origin name is in invalid format.
|
||||
clone.invalid.url=Repository URL is a malformed URL or non-existent directory.
|
||||
clone.origin=&Origin Name
|
||||
clone.parent.dir=&Parent Directory
|
||||
clone.parent.missing.error=The parent path {0} must exist.
|
||||
clone.repository.url=Git &Repository URL
|
||||
clone.test.failed.error=Repository test has failed.
|
||||
clone.test.success.message=<html>Connection to repository <tt>{0}</tt> has been successful.</html>
|
||||
clone.test.success=Connection successful
|
||||
clone.test=&Test
|
||||
clone.testing=Testing repository {0}
|
||||
clone.title=Clone Repository
|
||||
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=<html>Specify a commit author here if it is different from committer. The author should be in the format: Author Name <author@ema.il></html>
|
||||
commit.author=&Author:
|
||||
commit.partial.merge.message=<html>The following files are not included in commit.<ul>{0}</ul>Perform commit with all files included?</html>
|
||||
commit.partial.merge.title=Partial Merge Commit
|
||||
commit.push.changes.tooltip=When this option is enabled, changes are pushed to the server after commit.
|
||||
commit.push.changes=&Push Changes
|
||||
common.current.branch.tooltip=The currently checked out branch.
|
||||
common.current.branch=Current Branch:
|
||||
common.git.root.tooltip=Select git vcs root
|
||||
common.git.root=Git &Root:
|
||||
common.no.active.branch=<no active branch>
|
||||
computing.annotation=Computing annotation for {0}
|
||||
current.branch.action.name=CurrentBranch
|
||||
current.branch.change.tracked=Change Tracked Branch
|
||||
current.branch.message=Checked out branch: {0}
|
||||
current.branch.title=Current Branch
|
||||
current.branch.tracked.branch.none=<none>
|
||||
current.branch.tracked.branch.tooltip=Select the branch to track
|
||||
current.branch.tracked.branch=&Branch:
|
||||
current.branch.tracked.remote.none=<none>
|
||||
current.branch.tracked.remote.this=<this repository>
|
||||
current.branch.tracked.repository.tooltip=Select repository to track
|
||||
current.branch.tracked.repository=Re&pository:
|
||||
current.branch.tracked.title=Tracked Branch
|
||||
debug.git.exec=DEBUG: work-dir: [{0}] exec: [{1}]
|
||||
delete.action.name=Delete
|
||||
diff.find.error=Finding revision for diff: {0}
|
||||
error.dialog.title=Error
|
||||
error.list.title={0} Error:
|
||||
error.occurred.during=Error occurred during ''{0}''
|
||||
fetch.action.name=Fetch
|
||||
fetch.button=Fetch
|
||||
fetch.force.references.update.tooltip=Forces update of branch references for which update is not forced in refrence mapping.
|
||||
fetch.force.references.update=Force references &update
|
||||
fetch.remote.label=Re&mote:
|
||||
fetch.remote.tooltip=Remote name or url for fetch
|
||||
fetch.tags.label=Fetch &tags:
|
||||
fetch.tags.policy.all=All
|
||||
fetch.tags.policy.for.fetched.commits=For fetched commits
|
||||
fetch.tags.policy.none=None
|
||||
fetch.tags.tooltip=<html>Select fetched commits policy<ul><li><i>For fetched commits</i> means tags associated with commits on fetched branches are fetched.</li><li><i>All</i> means that all tags and reference commits are fetched</li><li><i>None</i> means that no tags are fetched.</li></ul></html>
|
||||
fetch.title=Git Fetch
|
||||
fetching.tags.title=Updating tags from {0}
|
||||
fetching.title=Fetching from {0}
|
||||
find.git.description=Select path to git executable
|
||||
find.git.error.title=Error Running git
|
||||
find.git.success.title=Git Executed Successfully
|
||||
find.git.title=Git Configuration
|
||||
find.git.unsupported.message=<html><tt>{0}</tt><br>This version is unsupported, and some plugin functionality could fail to work.<br>The minimal supported version is <em>{1}</em>.</html>
|
||||
fix.roots.button=Accept
|
||||
fix.roots.list.tooltip=The suggested list of Git VCS roots, new roots are marked as bold, removed roots are marked as overstriked.
|
||||
fix.roots.message=The following Git vcs roots will be used instead of the current Git VCS roots.
|
||||
fix.roots.title=Fix Git VCS Roots
|
||||
fix.roots.valid.message=The invalid Git roots have been fixed already.
|
||||
fix.roots.valid.title=All Git Roots Are Valid
|
||||
getting.history=Getting history for {0}
|
||||
git.default.commit.message=\n# Brief commit description here\n\n# Full commit description here (comment lines starting with '#' will not be included)\n\n
|
||||
git.error.exit=The git process exited with the code {0}
|
||||
git.running=<html>Running: {0}</html>
|
||||
git.vcs.config.path.label=Path to &git executable:
|
||||
git.vcs.config.ssh.mode.idea=IDEA ssh
|
||||
git.vcs.config.ssh.mode.native=Native
|
||||
git.vcs.config.ssh.mode.tooltip=<html>Specify which version of SSH to be used with git.<ul><li><b>Native</b> means that the native ssh will be used.</li><li><b>IDEA SSH</b> means that the implementation provided by the IDEA will be used.</li></ul>The native implementation might cause hangups on some platforms. In native case, you also might need to configure <em>ssh-askpass</em> for your platform to recieve GUI promopts for passwords.</html>
|
||||
git.vcs.config.ssh.mode=&SSH executable:
|
||||
git.vcs.config.test.label=Test
|
||||
git.vcs.config.test=&Test
|
||||
index.file.error=Updating file in the index failed
|
||||
init.add.root.message=Do you want to add this directory as vcs root?
|
||||
init.add.root.title=Git Init
|
||||
init.destination.directory.description=Select directory where the new Git repository will be created.
|
||||
init.destination.directory.title=Select directory for git init
|
||||
init.error.already.under.git=The selected directory {0} is already under git. The submodules are not yet supported.
|
||||
init.error.title=git init Error
|
||||
merge.action.name=Merge
|
||||
merge.add.log.information.tooltip=Add log information to the commit message (\"--log\" option)
|
||||
merge.add.log.information=Add &log information
|
||||
merge.branch.button=Merge
|
||||
merge.branch.message=Select branch to merge into this one ({0})
|
||||
merge.branch.title=Merge Branches
|
||||
merge.branches.tooltip=<html>The chooser for braches. Select one or more braches to merge (already merged branches are not shown)</html>.
|
||||
merge.branches=&Branches to merge:
|
||||
merge.commit.message.tooltip=The commit message to use in case if merge results in commit (\"-m\" option)
|
||||
merge.commit.message=Commit &Message
|
||||
merge.default.strategy=<default>
|
||||
merge.is.not.needed=Merge is not needed for the file {0}
|
||||
merge.load.files=Loading files for merge
|
||||
merge.no.commit.tooltip=Force no commit for merge (the \"--no-commit\" option)
|
||||
merge.no.commit=No &commit
|
||||
merge.no.fast.forward.tooltip=Disable fast forward (\"--no-ff\" option)
|
||||
merge.no.fast.forward=No &fast forward
|
||||
merge.retrieving.branches=Retrieving unmerged branches
|
||||
merge.squash.commit=S&quash commit
|
||||
merge.squash.tooltip=Squash all changes into the single commit (\"--squash\" option)
|
||||
merge.strategy.tooltip=The merge strategy to use (\"-s\" option)
|
||||
merge.strategy=&Strategy:
|
||||
merge.tool.action.name=MergeTool
|
||||
merge.tool.column.status.deleted=Deleted
|
||||
merge.tool.column.status.modified=Modified
|
||||
merge.tool.column.theirs.status=Theirs
|
||||
merge.tool.column.yours.status=Yours
|
||||
merging.branch=Merging branch {0}
|
||||
merging.title=Merging changes to {0}
|
||||
paths.affected.title=Paths affected in commit {0}
|
||||
pull.action.name=Pull
|
||||
pull.button=Pull
|
||||
pull.force.reference.update=Force reference &update
|
||||
pull.get.branches.tooltip=Get branch names from remote repository. Otherwise a locally cached information is used.
|
||||
pull.get.branches=&Get Branches
|
||||
pull.getting.remote.branches=Getting remote branches
|
||||
pull.remote.tooltip=Registered remote name or URL.
|
||||
pull.remote=Re&mote:
|
||||
pull.retrieving.remotes=Retrieving remotes
|
||||
pull.title=Pull changes
|
||||
pull.url.message=Enter remote repository URL to pull/merge (empty for default):
|
||||
pull.url.title=Pull URL
|
||||
pulling.title=Pulling changes from {0}
|
||||
push.action.name=Push
|
||||
push.branches.tooltip=Select branches to push
|
||||
push.branches=&Branches:
|
||||
push.button=Push
|
||||
push.force.update.tooltip=If selected remote ref is updated even if they are is not an ancestor of the local ref.
|
||||
push.force.update=&Force update
|
||||
push.policy.all=All
|
||||
push.policy.default=Default
|
||||
push.policy.mirror=Mirror
|
||||
push.policy.selected=Selected branches
|
||||
push.policy.tooltip=<html>Select push policy:<ul><li><em>Default</em> - the push is done according to the configuration of the remote.</li><li><em>Selected branches</em> - selected branches are pushed.</li><li><em>All</em> - all references under refs/heads are pushed.</li><li><em>Mirror</em> - all references under refs/ are pushed including tags and remotes.</li></ul></html>
|
||||
push.policy=&Push:
|
||||
push.remote.tooltip=Specify remote repository URL or remote name where to push changes.
|
||||
push.remote=Re&mote:
|
||||
push.show.tags.tooltip=If selected, the tags are shown in branch chooser as well.
|
||||
push.show.tags=Show ta&gs
|
||||
push.tags.tooltip=All tag refereneces are pushed in addition to references specified in references section.
|
||||
push.tags=Push &tags
|
||||
push.title=Push Changes
|
||||
push.use.thin.pack.tooltip=If this option is selected, the push will spend extra CPU cycles to minimize amount of data transferred (use it for slow connections)
|
||||
push.use.thin.pack=&Use thin pack
|
||||
pushing.all.changes=Pushing all commited changes, refs & tags to remote repos
|
||||
rebase.abort.action.name=Abort Rebasing
|
||||
rebase.action.error=Git Rebase Error
|
||||
rebase.action.message=Mulitple git roots have unfinished rebase process, please select root to perform action on.
|
||||
rebase.action.name=Rebase
|
||||
rebase.action.no.root=There is no rebase operation in progress in the project
|
||||
rebase.branch.tooltip=Select branch to rebase (if branch is different from the current branch, it will be checked out first)
|
||||
rebase.branch=&Branch:
|
||||
rebase.button=Rebase
|
||||
rebase.continue.action.name=Continue Rebasing
|
||||
rebase.editor.action.column=Action
|
||||
rebase.editor.button=Start Rebasing
|
||||
rebase.editor.comment.column=Comment
|
||||
rebase.editor.commit.column=Commit
|
||||
rebase.editor.invalid.entryset=No commits found to rebase
|
||||
rebase.editor.invalid.squash=The first non-skip commint could not be marked as squashed since squash merges commit with the previous commit.
|
||||
rebase.editor.message=Reorder and edit &rebased commits
|
||||
rebase.editor.move.down.tooltip=Move commit down (commit will be applied later)
|
||||
rebase.editor.move.down=Move &Down
|
||||
rebase.editor.move.up.tooltip=Move commit up in the list (commit will be applied earlier)
|
||||
rebase.editor.move.up=Move &Up
|
||||
rebase.editor.title=Rebasing commits
|
||||
rebase.editor.view.tooltip=View commit contents
|
||||
rebase.editor.view=&View
|
||||
rebase.from.tooltip=Sepecify actual base for the branch. Leave blank to onto.
|
||||
rebase.from=&From:
|
||||
rebase.in.progress=Interactive rebase has been already started for this git root.
|
||||
rebase.interactive.tooltip=If selected, the interactive rebase will be preformed.
|
||||
rebase.interactive=&Interactive
|
||||
rebase.invalid.from=\"From\" reference expression is invalid.
|
||||
rebase.invalid.onto=\"Onto\" reference expression is invalid.
|
||||
rebase.merge.strategy.tooltip=Select merge strategy to use
|
||||
rebase.merge.strategy=Merge &Strategy:
|
||||
rebase.no.merge.tooltip=If selected, no merge strategies will be applied during the rebase.
|
||||
rebase.no.merge=&Do not use merge strategies
|
||||
rebase.onto.tooltip=The reference that will become a new base for selected branch.
|
||||
rebase.onto.validate=&Validate
|
||||
rebase.onto=&Onto:
|
||||
rebase.preserve.merges.tooltip=Preserve merges during rebease instead of squashing them.
|
||||
rebase.preserve.merges=&Preserve Merges
|
||||
rebase.result.amend.title=Rebase Suspended
|
||||
rebase.result.amend=Stopped for amending commit while rebasing ({0}/{1}).\nAmmed commit and continue the rebase process.
|
||||
rebase.result.cancelled.title=Rebase Cancelled
|
||||
rebase.result.cancelled=The rebase process was cancelled.
|
||||
rebase.result.conflict.title=Rebase Suspended
|
||||
rebase.result.conflict=Stopped rebasing because of conflict ({0}/{1}).\nResolve conflicts and continue the rebase process.
|
||||
rebase.result.error.title=Rebase Error
|
||||
rebase.result.error=Stopped rebasing because of error while rebasing ({0}/{1}).\nCheck vcs console for details.
|
||||
rebase.show.remote.branches.tooltip=If selected, remote branches are shown in drop down as well.
|
||||
rebase.show.remote.branches=Show Re&mote Branches
|
||||
rebase.show.tags.tooltip=Show tags in \"from\" and \"onto\" dropdowns.
|
||||
rebase.skip.action.name=Skip Commit in Rebasing
|
||||
rebase.title=Rebase branch
|
||||
rebase.unstructured.editor.button=Resume Rebasing
|
||||
rebase.unstructured.editor.git.root=Git Root:
|
||||
rebase.unstructured.editor.message=Git rebase operation requested additional &information through the editor:
|
||||
rebase.unstructured.editor.title=Addtional Rebase Input
|
||||
rebase.unstructured.editor.tooltip=Edit this text according to instructions provided inline
|
||||
rebase.valdate.onto.tooltip=Valdate "onto" reference.
|
||||
rebase.validate.from.tooltip=Validate \"from\" reference
|
||||
rebase.validate.from=Va&lidate
|
||||
rebasing.title=Rebasing...
|
||||
refspec.add.all.branches.tooltip=Add refspec that maps all remote branches by glob spec.
|
||||
refspec.add.all.branches=Add A&ll Branches
|
||||
refspec.add.all.tags.tooltip=Adds mapping entry for all tags
|
||||
refspec.add.all.tags=Add All Ta&gs
|
||||
refspec.add.ref.tooltip=Add branch or tag by name
|
||||
refspec.add.ref=&Add...
|
||||
refspec.branch.prefix.tooltip=Specify default branch prefix for the mapping.
|
||||
refspec.branch.prefix=Remote &Name:
|
||||
refspec.column.force=Force
|
||||
refspec.column.local=Local
|
||||
refspec.column.remote=Remote
|
||||
refspec.default.tooltip=Restore default reference mapping
|
||||
refspec.default=&Default
|
||||
refspec.remove.tooltip=Delete refspec entry
|
||||
refspec.remove=Remo&ve
|
||||
refspec.title=Reference mapping
|
||||
refspec.validation.remote.invalid=The invalid local name for remote
|
||||
refspec.validation.remote.is.blank=The local name for remote is blank
|
||||
regase.show.tags=Show &tags
|
||||
repository.action.missing.roots.misconfigured=Neither of configured git roots are is under git. The configured directory or some of its ancestors must have ".git" directory in it.
|
||||
repository.action.missing.roots.title=No git roots
|
||||
repository.action.missing.roots.unconfigured.message=No git roots are configured for the project.
|
||||
reset.action.name=Reset Head ...
|
||||
reset.button=Reset
|
||||
reset.commit.invalid=The specified commit expression did not pass validation.
|
||||
reset.commit.label=To &Commit:
|
||||
reset.commit.tooltip=The commit that will become the current HEAD\n as result of reset operation.
|
||||
reset.title=Reset Head
|
||||
reset.type.hard=Hard
|
||||
reset.type.mixed=Mixed
|
||||
reset.type.soft=Soft
|
||||
reset.type.tooltip=<html>The reset type (see also <code>git reset</code> man page):<ul><li><b>Mixed</b> resets index but not working tree</li><li><b>Soft</b> leaves index and working tree, just moves head pointer</li><li><b>Hard</b> resets index and working tree.<em>Changes in the working tree will be lost</em></li></ul></html>
|
||||
reset.type=Reset &Type:
|
||||
reset.validate.tooltip=Validate the commit pointer and check the content of referenced commit.
|
||||
reset.validate=&Validate
|
||||
resetting.title=Resetting HEAD...
|
||||
revert.action.name=Revert
|
||||
revision.graph=RevisionGraph
|
||||
root.tracker.message=Some configured Git VCS roots are not under Git or have Git repositories in subdirectories without configured VCS root.
|
||||
select.branch.to.checkout=Select branch to checkout
|
||||
show.all.paths.affected.action.name=Show All Affected Paths
|
||||
ssh.ask.passphrase.title=SSH Key Passphrase
|
||||
ssh.askPassphrase.message=Please enter passphrase for the private key {0} (the user name is {1})
|
||||
ssh.changed.host.key=<html>The server host key for the host {0}:{1} has changed to {2} (type {3}).\nDo you want to accept the changed key?</html>
|
||||
ssh.confirm.key.titile=Confirm SSH Server Key
|
||||
ssh.error.title=Authentication error
|
||||
ssh.keyboard.interactive.title=SSH Keyboard Interactive: {0}
|
||||
ssh.keyboard.interactive.username=Username:
|
||||
ssh.new.host.key=<html>Connecting to a new host {0}:{1} that has the key {2} (type {3}).\nDo you want to add this host to known hosts database?</html>
|
||||
ssh.password.message=Please enter password for user {0}
|
||||
ssh.password.title=SSH Password Login
|
||||
sshmain.failed.to.verify.key=Failed to verify key: {0}
|
||||
sshmain.forwarding.failed=Forwarding {0} failed: {1}
|
||||
sshmain.invald.host.key=Invald host key {0} {1}
|
||||
sshmain.invalid.amount.of.arguments=Invalid amount of arguments: {0}
|
||||
sshmain.invalidpassphrase=Invalid passphrase for the key {0}
|
||||
sshmain.keyboard.interactive.failed=Keyboard interactive authentication failed.
|
||||
sshmain.password.failed=Invalid user or password.
|
||||
sshmain.pk.authenitication.failed=Authentication using key {0} failed.
|
||||
sshmain.too.mush.passphrase.guesses=Invalid passphrase for the key {0}({1} attempts)
|
||||
stash.action.name=Stash
|
||||
stash.button=Create Stash
|
||||
stash.keep.index.tooltip=If this checkbox is selected, indexed changes are kept in the index.
|
||||
stash.keep.index=Keep &index
|
||||
stash.message.tooltip=Enter stash message here.
|
||||
stash.message=&Message:
|
||||
stash.title=Stash
|
||||
stashing.title=Stashing changes...
|
||||
tag.action.name=Tag
|
||||
tag.button=Create Tag
|
||||
tag.commit.label=&Commit:
|
||||
tag.commit.tooltip=Enter name of commit or object to tag or leave blank to use HEAD.
|
||||
tag.error.creating.message.file.message=Unable to create message file: {0}
|
||||
tag.error.creating.message.file.title=Error creating message file
|
||||
tag.error.invalid.commit=The commit or object name is invalid.
|
||||
tag.error.tag.exists=The tag with the same name exists.
|
||||
tag.force.tooltip=Force creation of the text even if tag with such name already exists.
|
||||
tag.force=&Force
|
||||
tag.getting.existing.tags=Getting existing tags...
|
||||
tag.message.label=&Message:
|
||||
tag.message.tooltip=If the message is not empty, an annotated tag is created.
|
||||
tag.message=Specify tag name:
|
||||
tag.name.label=Tag &Name:
|
||||
tag.name.tooltip=Enter the new tag name here.
|
||||
tag.nonvcs.error.message=ERROR: Files not tagged, not all are under VCS root!
|
||||
tag.nonvcs.error.title=Tag Result
|
||||
tag.title=Tag
|
||||
tag.validate.tooltip=Click this button to the validate commit to be tagged.
|
||||
tag.validate=&Validate
|
||||
tagging.title=Tagging files...
|
||||
unindexed.files.changlelist.name=Unindexed Files
|
||||
unstash.action.name=UnStash
|
||||
unstash.branch.label\:=As new &branch:
|
||||
unstash.branch.tooltip=If non-empty name is entered, the stash is checked out as a new branch.
|
||||
unstash.button.apply=Apply Stash
|
||||
unstash.button.branch=Branch
|
||||
unstash.button.pop=Pop Stash
|
||||
unstash.clear.tooltip=Delete all stashes in the repository.
|
||||
unstash.clear=&Clear
|
||||
unstash.clearing.stashes=Clearing stashes...
|
||||
unstash.drop.tooltip=Delete selected stash
|
||||
unstash.drop=&Drop
|
||||
unstash.dropping.stash=Dropping stash {0}...
|
||||
unstash.error.branch.exists=The specified branch already exists
|
||||
unstash.error.invalid.branch.name=Invalid branch name
|
||||
unstash.pop.stash.tooltip=If selected the stash is dropped after it is applied.
|
||||
unstash.pop.stash=&Pop stash
|
||||
unstash.reinstate.index.tooltip=Attempt to reinstate index as well as working tree changes.
|
||||
unstash.reinstate.index=Reinstate &index
|
||||
unstash.stashes.item=<html><b><tt>{0}</tt></b>:<i>{1}</i>:{2}</html>
|
||||
unstash.stashes.tooltip=Select a stash to operate for.
|
||||
unstash.stashes=&Stashes:
|
||||
unstash.title=UnStash Changes
|
||||
unstash.view.tooltip=View selected stash
|
||||
unstash.view=&View
|
||||
unstashing.title=UnStashing changes...
|
||||
update.options.display.name=Git Update Settings
|
||||
update.options.no.commit=No &Commit
|
||||
update.options.stash.tooltip=If selected, the current changes will be stashed before update, and than restored after update.
|
||||
update.options.stash=&Stash changes before update
|
||||
update.options.type.default=Branch Default
|
||||
update.options.type.merge=Force Merge
|
||||
update.options.type.rebase=Force Rebase
|
||||
update.options.type.tooltip=Force update type (merge or rebase) or use branch default configuration
|
||||
update.options.type=&Type:
|
||||
update.rebase.no.change.cancel=Cancel Update
|
||||
update.rebase.no.change.retry=Retry Continue
|
||||
update.rebase.no.change.skip=Skip Commit
|
||||
update.rebase.no.change.title=No Changes Staged
|
||||
update.rebase.no.change=<html>No changes detected <tt>{0}</tt>. <ul><li>Skip Commit - skips current commit in the rebase process</li><li>Retry Continue - do it after you add changes to commit manually</li><li>Or cancel cancels update process for this root.</li></ul></html>
|
||||
update.rebase.unmerged.title=Unresolved Rebase Conflicts
|
||||
update.rebase.unmerged=<html><b>{0}</b> file(s) are not yet merged. Repeat merge operation (no cancels update for root <tt>{1}</tt>?</html>
|
||||
util.remote.renderer.default=<html><b>{0}</b>(<i>{1}</i>)</html>
|
||||
util.remote.renderer.none=<html><i>None</i></html>
|
||||
util.remote.renderer.normal=<html><b>{0}</b>(<i>{1}</i>)</html>
|
||||
util.remote.renderer.self=<html><i>Current repository</i></html>
|
||||
vcs.unable.to.run.git=Unable to run git: {0} ({1})
|
||||
vcs.unsupported.version=Unsupported version of git configured: {0}. The minimal supported version is {1}
|
||||
vfs.listener.add.single.prompt=Do you want to add the following file to Git?\n{0}\n\nIf you say NO, you can still add it later manually.
|
||||
vfs.listener.add.single.title=Add file to Git
|
||||
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
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package git4idea.update;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.commands.GitHandler;
|
||||
import git4idea.commands.GitSimpleHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* The class contains utilities for creating and removing stashes.
|
||||
*/
|
||||
public class GitStashUtils {
|
||||
private GitStashUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create stash for later use
|
||||
*
|
||||
* @param project the project to use
|
||||
* @param root the root
|
||||
* @param message the message for the stash
|
||||
* @return true if the stash was created, false otherwise
|
||||
*/
|
||||
public static boolean saveStash(@NotNull Project project, @NotNull VirtualFile root, final String message) throws VcsException {
|
||||
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitHandler.STASH);
|
||||
handler.setNoSSH(true);
|
||||
handler.addParameters("save", message);
|
||||
String output = handler.run();
|
||||
return !output.startsWith("No local changes to save");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create stash for later use
|
||||
*
|
||||
* @param project the project to use
|
||||
* @param root the root
|
||||
*/
|
||||
public static void popLastStash(@NotNull Project project, @NotNull VirtualFile root) throws VcsException {
|
||||
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitHandler.STASH);
|
||||
handler.setNoSSH(true);
|
||||
handler.addParameters("pop");
|
||||
handler.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package git4idea.update;
|
||||
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Configurable for the update session
|
||||
*/
|
||||
public class GitUpdateConfigurable implements Configurable {
|
||||
/** The vcs settings for the configurable */
|
||||
private final GitVcsSettings mySettings;
|
||||
/** The options panel */
|
||||
private GitUpdateOptionsPanel myPanel;
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
* @param settings the settings object
|
||||
*/
|
||||
public GitUpdateConfigurable(GitVcsSettings settings) {
|
||||
mySettings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Nls
|
||||
public String getDisplayName() {
|
||||
return GitBundle.getString("update.options.display.name");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Icon getIcon() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getHelpTopic() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public JComponent createComponent() {
|
||||
myPanel = new GitUpdateOptionsPanel();
|
||||
return myPanel.getPanel(); //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isModified() {
|
||||
return myPanel.isModified(mySettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void apply() throws ConfigurationException {
|
||||
myPanel.applyTo(mySettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void reset() {
|
||||
myPanel.updateFrom(mySettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void disposeUIResources() {
|
||||
myPanel = null;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,10 @@ import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vcs.AbstractVcsHelper;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.update.SequentialUpdatesContext;
|
||||
@@ -27,13 +30,15 @@ import com.intellij.openapi.vcs.update.UpdateEnvironment;
|
||||
import com.intellij.openapi.vcs.update.UpdateSession;
|
||||
import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitRevisionNumber;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.commands.GitHandler;
|
||||
import git4idea.commands.GitHandlerUtil;
|
||||
import git4idea.commands.GitLineHandler;
|
||||
import git4idea.config.GitConfigUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.changes.GitChangeUtils;
|
||||
import git4idea.commands.*;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import git4idea.merge.MergeChangeCollector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -42,24 +47,35 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Git update environment implementation. The environment does just a simple
|
||||
* {@code git pull -v} for each content root.
|
||||
*/
|
||||
public class GitUpdateEnvironment implements UpdateEnvironment {
|
||||
/**
|
||||
* The vcs instance
|
||||
*/
|
||||
private GitVcs myVcs;
|
||||
/**
|
||||
* The context project
|
||||
*/
|
||||
private final Project myProject;
|
||||
/**
|
||||
* The project settings
|
||||
*/
|
||||
private final GitVcsSettings mySettings;
|
||||
|
||||
/**
|
||||
* A constructor from settings
|
||||
*
|
||||
* @param project a project
|
||||
*/
|
||||
public GitUpdateEnvironment(@NotNull Project project) {
|
||||
public GitUpdateEnvironment(@NotNull Project project, @NotNull GitVcs vcs, GitVcsSettings settings) {
|
||||
myVcs = vcs;
|
||||
myProject = project;
|
||||
mySettings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,33 +95,131 @@ public class GitUpdateEnvironment implements UpdateEnvironment {
|
||||
@NotNull Ref<SequentialUpdatesContext> sequentialUpdatesContextRef)
|
||||
throws ProcessCanceledException {
|
||||
List<VcsException> exceptions = new ArrayList<VcsException>();
|
||||
for (VirtualFile root : GitUtil.gitRoots(Arrays.asList(filePaths))) {
|
||||
for (final VirtualFile root : GitUtil.gitRoots(Arrays.asList(filePaths))) {
|
||||
try {
|
||||
// check if there is a remote for the branch
|
||||
final GitBranch branch = GitBranch.current(myProject, root);
|
||||
if (branch == null) {
|
||||
continue;
|
||||
}
|
||||
final String value = GitConfigUtil.getValue(myProject, root, "branch." + branch.getName() + ".remote");
|
||||
final String value = branch.getTrackedRemoteName(myProject, root);
|
||||
if (value == null || value.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
// remember the current position
|
||||
GitRevisionNumber before = GitRevisionNumber.resolve(myProject, root, "HEAD");
|
||||
// do pull
|
||||
GitLineHandler h = new GitLineHandler(myProject, root, GitHandler.PULL);
|
||||
// ignore merge failure for the pull
|
||||
h.ignoreErrorCode(1);
|
||||
h.addParameters("--no-stat");
|
||||
h.addParameters("-v");
|
||||
boolean stashCreated =
|
||||
mySettings.UPDATE_STASH && GitStashUtils.saveStash(myProject, root, "Uncommitted changes before update operation");
|
||||
try {
|
||||
GitHandlerUtil.doSynchronouslyWithExceptions(h, progressIndicator);
|
||||
// remember the current position
|
||||
GitRevisionNumber before = GitRevisionNumber.resolve(myProject, root, "HEAD");
|
||||
// do pull
|
||||
GitLineHandler h = new GitLineHandler(myProject, root, GitHandler.PULL);
|
||||
// ignore merge failure for the pull
|
||||
h.ignoreErrorCode(1);
|
||||
switch (mySettings.UPDATE_TYPE) {
|
||||
case REBASE:
|
||||
h.addParameters("--rebase");
|
||||
break;
|
||||
case MERGE:
|
||||
h.addParameters("--no-rebase");
|
||||
break;
|
||||
case BRANCH_DEFAULT:
|
||||
// use default for the branch
|
||||
break;
|
||||
default:
|
||||
assert false : "Unknown update type: " + mySettings.UPDATE_TYPE;
|
||||
}
|
||||
h.addParameters("--no-stat");
|
||||
h.addParameters("-v");
|
||||
final Ref<Boolean> cancelled = new Ref<Boolean>(false);
|
||||
try {
|
||||
RebaseConflictDetector rebaseConflictDetector = new RebaseConflictDetector();
|
||||
h.addLineListener(rebaseConflictDetector);
|
||||
try {
|
||||
GitHandlerUtil.doSynchronouslyWithExceptions(h, progressIndicator);
|
||||
}
|
||||
finally {
|
||||
if (!rebaseConflictDetector.isRebaseConflict()) {
|
||||
exceptions.addAll(h.errors());
|
||||
}
|
||||
}
|
||||
do {
|
||||
final Ref<Throwable> ex = new Ref<Throwable>();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
List<VirtualFile> affectedFiles = GitChangeUtils.unmergedFiles(myProject, root);
|
||||
while (affectedFiles.size() != 0) {
|
||||
AbstractVcsHelper.getInstance(myProject).showMergeDialog(affectedFiles, myVcs.getMergeProvider());
|
||||
affectedFiles = GitChangeUtils.unmergedFiles(myProject, root);
|
||||
if (affectedFiles.size() != 0) {
|
||||
int result = Messages.showYesNoDialog(myProject, GitBundle.message("update.rebase.unmerged", affectedFiles.size(),
|
||||
root.getPresentableUrl()),
|
||||
GitBundle.getString("update.rebase.unmerged.title"), Messages.getErrorIcon());
|
||||
if (result != 0) {
|
||||
cancelled.set(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
ex.set(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
//noinspection ThrowableResultOfMethodCallIgnored
|
||||
if (ex.get() != null) {
|
||||
//noinspection ThrowableResultOfMethodCallIgnored
|
||||
throw GitUtil.rethrowVcsException(ex.get());
|
||||
}
|
||||
if (cancelled.get()) {
|
||||
break;
|
||||
}
|
||||
doRebase(progressIndicator, root, rebaseConflictDetector, "--continue");
|
||||
final Ref<Integer> result = new Ref<Integer>();
|
||||
noChangeLoop:
|
||||
while (rebaseConflictDetector.isNoChange()) {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
int rc = Messages.showDialog(myProject, GitBundle.message("update.rebase.no.change", root.getPresentableUrl()),
|
||||
GitBundle.getString("update.rebase.no.change.title"),
|
||||
new String[]{GitBundle.getString("update.rebase.no.change.skip"),
|
||||
GitBundle.getString("update.rebase.no.change.retry"),
|
||||
GitBundle.getString("update.rebase.no.change.cancel")}, 0, Messages.getErrorIcon());
|
||||
result.set(rc);
|
||||
}
|
||||
});
|
||||
switch (result.get()) {
|
||||
case 0:
|
||||
doRebase(progressIndicator, root, rebaseConflictDetector, "--skip");
|
||||
continue noChangeLoop;
|
||||
case 1:
|
||||
continue noChangeLoop;
|
||||
case 2:
|
||||
cancelled.set(true);
|
||||
break noChangeLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (rebaseConflictDetector.isRebaseConflict() && !cancelled.get());
|
||||
if (cancelled.get()) {
|
||||
//noinspection ThrowableInstanceNeverThrown
|
||||
exceptions.add(new VcsException("The update process was cancelled for " + root.getPresentableUrl()));
|
||||
doRebase(progressIndicator, root, rebaseConflictDetector, "--abort");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (!cancelled.get()) {
|
||||
// find out what have changed
|
||||
MergeChangeCollector collector = new MergeChangeCollector(myProject, root, before, updatedFiles);
|
||||
collector.collect(exceptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
exceptions.addAll(h.errors());
|
||||
// find out what have changed
|
||||
MergeChangeCollector collector = new MergeChangeCollector(myProject, root, before, updatedFiles);
|
||||
collector.collect(exceptions);
|
||||
if (stashCreated) {
|
||||
GitStashUtils.popLastStash(myProject, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (VcsException ex) {
|
||||
@@ -115,6 +229,26 @@ public class GitUpdateEnvironment implements UpdateEnvironment {
|
||||
return new GitUpdateSession(exceptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do rebase operation as part of update operator
|
||||
*
|
||||
* @param progressIndicator the progress indicator for the update
|
||||
* @param root the vcs root
|
||||
* @param rebaseConflictDetector the detector of conflicts in rebase operation
|
||||
* @param action the rebase action to execute
|
||||
*/
|
||||
private void doRebase(ProgressIndicator progressIndicator,
|
||||
VirtualFile root,
|
||||
RebaseConflictDetector rebaseConflictDetector,
|
||||
final String action) {
|
||||
GitLineHandler rh = new GitLineHandler(myProject, root, GitHandler.REBASE);
|
||||
// ignore failure for abort
|
||||
rh.ignoreErrorCode(1);
|
||||
rh.addParameters(action);
|
||||
rebaseConflictDetector.reset();
|
||||
rh.addLineListener(rebaseConflictDetector);
|
||||
GitHandlerUtil.doSynchronouslyWithExceptions(rh, progressIndicator);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@@ -133,6 +267,63 @@ public class GitUpdateEnvironment implements UpdateEnvironment {
|
||||
*/
|
||||
@Nullable
|
||||
public Configurable createConfigurable(Collection<FilePath> files) {
|
||||
return null;
|
||||
return new GitUpdateConfigurable(mySettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* The detector of conflict conditions for rebase operation
|
||||
*/
|
||||
static class RebaseConflictDetector extends GitLineHandlerAdapter {
|
||||
/**
|
||||
* The line that indicates that there is a rebase conflict.
|
||||
*/
|
||||
private final static String REBASE_CONFLICT_INDICATOR = "When you have resolved this problem run \"git rebase --continue\".";
|
||||
/**
|
||||
* The line that indicates "no change" condition.
|
||||
*/
|
||||
private static final String REBASE_NO_CHANGE_INDICATOR = "No changes - did you forget to use 'git add'?";
|
||||
/**
|
||||
* if true, the rebase conflict happened
|
||||
*/
|
||||
AtomicBoolean rebaseConflict = new AtomicBoolean(false);
|
||||
/**
|
||||
* if true, the no changes were detected in the rebase operations
|
||||
*/
|
||||
AtomicBoolean noChange = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* Reset detector before new operation
|
||||
*/
|
||||
public void reset() {
|
||||
rebaseConflict.set(false);
|
||||
noChange.set(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if "no change" condition was detected during the operation
|
||||
*/
|
||||
public boolean isNoChange() {
|
||||
return noChange.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if conflict during rebase was detected
|
||||
*/
|
||||
public boolean isRebaseConflict() {
|
||||
return rebaseConflict.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
if (line.startsWith(REBASE_CONFLICT_INDICATOR)) {
|
||||
rebaseConflict.set(true);
|
||||
}
|
||||
if (line.startsWith(REBASE_NO_CHANGE_INDICATOR)) {
|
||||
noChange.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="git4idea.update.GitUpdateOptionsPanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="332" height="82"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="1d8b2" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="b73c5"/>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="update.options.type"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="a20d7" class="javax.swing.JCheckBox" binding="myStashChangesCheckBox">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="update.options.stash"/>
|
||||
<toolTipText resource-bundle="git4idea/i18n/GitBundle" key="update.options.stash.tooltip"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="f5eba" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<hspacer id="c2e96">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<component id="b73c5" class="javax.swing.JComboBox" binding="myTypeComboBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<toolTipText resource-bundle="git4idea/i18n/GitBundle" key="update.options.type.tooltip"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<vspacer id="d3b1e">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -0,0 +1,113 @@
|
||||
package git4idea.update;
|
||||
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.config.GitVcsSettings.UpdateType;
|
||||
import git4idea.i18n.GitBundle;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Update options
|
||||
*/
|
||||
public class GitUpdateOptionsPanel {
|
||||
/**
|
||||
* The merge policy
|
||||
*/
|
||||
private static final String MERGE = GitBundle.getString("update.options.type.merge");
|
||||
/**
|
||||
* The rebase policy
|
||||
*/
|
||||
private static final String REBASE = GitBundle.getString("update.options.type.rebase");
|
||||
/**
|
||||
* The rebase policy
|
||||
*/
|
||||
private static final String DEFAULT = GitBundle.getString("update.options.type.default");
|
||||
/**
|
||||
* The type combobox
|
||||
*/
|
||||
private JComboBox myTypeComboBox;
|
||||
/**
|
||||
* The stash changes checkbox
|
||||
*/
|
||||
private JCheckBox myStashChangesCheckBox;
|
||||
/**
|
||||
* The root panel
|
||||
*/
|
||||
private JPanel myPanel;
|
||||
|
||||
/**
|
||||
* A constructor
|
||||
*/
|
||||
public GitUpdateOptionsPanel() {
|
||||
myTypeComboBox.addItem(DEFAULT);
|
||||
myTypeComboBox.addItem(REBASE);
|
||||
myTypeComboBox.addItem(MERGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the panel component
|
||||
*/
|
||||
public JComponent getPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the panel is modified relatively to settings
|
||||
* @param settings the settings to compare to
|
||||
* @return true if the UI modified the settings
|
||||
*/
|
||||
public boolean isModified(GitVcsSettings settings) {
|
||||
UpdateType type = getUpdateType();
|
||||
return type != settings.UPDATE_TYPE || myStashChangesCheckBox.isSelected() != settings.UPDATE_STASH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return get the currently selected update type
|
||||
*/
|
||||
private UpdateType getUpdateType() {
|
||||
UpdateType type = null;
|
||||
String typeVal = (String)myTypeComboBox.getSelectedItem();
|
||||
if (REBASE.equals(typeVal)) {
|
||||
type = UpdateType.REBASE;
|
||||
}
|
||||
else if (MERGE.equals(typeVal)) {
|
||||
type = UpdateType.MERGE;
|
||||
} else if(DEFAULT.equals(typeVal)) {
|
||||
type = UpdateType.BRANCH_DEFAULT;
|
||||
}
|
||||
assert type != null;
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save configuration to settings object
|
||||
* @param settings the settings to save to
|
||||
*/
|
||||
public void applyTo(GitVcsSettings settings) {
|
||||
settings.UPDATE_TYPE = getUpdateType();
|
||||
settings.UPDATE_STASH = myStashChangesCheckBox.isSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update panel according to settings
|
||||
* @param settings the settings to use
|
||||
*/
|
||||
public void updateFrom(GitVcsSettings settings) {
|
||||
myStashChangesCheckBox.setSelected(settings.UPDATE_STASH);
|
||||
String value = null;
|
||||
switch(settings.UPDATE_TYPE) {
|
||||
case REBASE:
|
||||
value = REBASE;
|
||||
break;
|
||||
case MERGE:
|
||||
value = MERGE;
|
||||
break;
|
||||
case BRANCH_DEFAULT:
|
||||
value = DEFAULT;
|
||||
break;
|
||||
default:
|
||||
assert false : "Unknown value of update type: "+settings.UPDATE_TYPE;
|
||||
}
|
||||
myTypeComboBox.setSelectedItem(value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user