private static boolean pushCurrentBranch( @NotNull Project project, @NotNull GitRepository repository, @NotNull String remoteName, @NotNull String remoteUrl, @NotNull String name, @NotNull String url) { Git git = ServiceManager.getService(Git.class); GitLocalBranch currentBranch = repository.getCurrentBranch(); if (currentBranch == null) { GithubNotifications.showErrorURL( project, "Can't finish GitHub sharing process", "Successfully created project ", "'" + name + "'", " on GitHub, but initial push failed: no current branch", url); return false; } GitCommandResult result = git.push(repository, remoteName, remoteUrl, currentBranch.getName(), true); if (!result.success()) { GithubNotifications.showErrorURL( project, "Can't finish GitHub sharing process", "Successfully created project ", "'" + name + "'", " on GitHub, but initial push failed:<br/>" + result.getErrorOutputAsHtmlString(), url); return false; } return true; }
@NotNull private static FetchParams getFetchParams(@NotNull GitRepository repository) { GitLocalBranch currentBranch = repository.getCurrentBranch(); if (currentBranch == null) { // fetching current branch is called from Update Project and Push, where branch tracking is // pre-checked String message = "Current branch can't be null here. \nRepository: " + repository; LOG.error(message); return new FetchParams(GitFetchResult.error(new Exception(message))); } GitBranchTrackInfo trackInfo = GitBranchUtil.getTrackInfoForBranch(repository, currentBranch); if (trackInfo == null) { String message = "Tracked info is null for branch " + currentBranch + "\n Repository: " + repository; LOG.error(message); return new FetchParams(GitFetchResult.error(new Exception(message))); } GitRemote remote = trackInfo.getRemote(); String url = remote.getFirstUrl(); if (url == null) { String message = "URL is null for remote " + remote.getName(); LOG.error(message); return new FetchParams(GitFetchResult.error(new Exception(message))); } return new FetchParams(remote, trackInfo.getRemoteBranch(), url); }
/** * Returns the tracking information (remote and the name of the remote branch), or null if we are * not on a branch. */ @Nullable public static GitBranchTrackInfo getTrackInfoForCurrentBranch(@NotNull GitRepository repository) { GitLocalBranch currentBranch = repository.getCurrentBranch(); if (currentBranch == null) { return null; } return GitBranchUtil.getTrackInfoForBranch(repository, currentBranch); }
/** Performs the actual sync/stash needed before attaching. */ private void syncOrStash() { // When the user edits a document in intelliJ, there are spurious updates to the timestamp of // the document for an unspecified amount of time (even though there are no real edits). // So, we save-all right before we stash to (help) ensure we don't get a conflict dialog. // The conflict dialog happens when the timestamps of the document and file are mismatched. // So when we do the git operations, we want the document and file timestamps to match exactly. BasicAction.saveAll(); mySourceRepository = mySyncResult.getLocalRepository(); if (mySyncResult.needsStash() || mySyncResult.needsSync()) { if (mySourceRepository.getCurrentBranch() != null) { myOriginalBranchName = mySourceRepository.getCurrentBranch().getName(); } else { myOriginalBranchName = mySourceRepository.getCurrentRevision(); } } if (mySyncResult.needsStash()) { if (!stash()) { return; } } if (!Strings.isNullOrEmpty(mySyncResult.getTargetSyncSHA())) { // try to check out that revision. final GitBrancher brancher = ServiceManager.getService(myProject, GitBrancher.class); if (mySourceRepository == null) { LOG.error("unexpected null source repo with a target SHA."); return; } assert mySyncResult.getTargetSyncSHA() != null; brancher.checkout( mySyncResult.getTargetSyncSHA(), Collections.singletonList(mySourceRepository), new Runnable() { @Override public void run() { refreshAndClose(); } }); } else { refreshAndClose(); } }
@Nullable public static GithubCreatePullRequestWorker createPullRequestWorker( @NotNull final Project project, @Nullable final VirtualFile file) { Git git = ServiceManager.getService(Git.class); GitRepository gitRepository = GithubUtil.getGitRepository(project, file); if (gitRepository == null) { GithubNotifications.showError( project, CANNOT_CREATE_PULL_REQUEST, "Can't find git repository"); return null; } gitRepository.update(); Pair<GitRemote, String> remote = GithubUtil.findGithubRemote(gitRepository); if (remote == null) { GithubNotifications.showError( project, CANNOT_CREATE_PULL_REQUEST, "Can't find GitHub remote"); return null; } String remoteName = remote.getFirst().getName(); String remoteUrl = remote.getSecond(); GithubFullPath path = GithubUrlUtil.getUserAndRepositoryFromRemoteUrl(remoteUrl); if (path == null) { GithubNotifications.showError( project, CANNOT_CREATE_PULL_REQUEST, "Can't process remote: " + remoteUrl); return null; } GitLocalBranch currentBranch = gitRepository.getCurrentBranch(); if (currentBranch == null) { GithubNotifications.showError(project, CANNOT_CREATE_PULL_REQUEST, "No current branch"); return null; } GithubAuthData auth; try { auth = GithubUtil.computeValueInModal( project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubAuthData, IOException>() { @Override public GithubAuthData convert(ProgressIndicator indicator) throws IOException { return GithubUtil.getValidAuthDataFromConfig(project, indicator); } }); } catch (GithubAuthenticationCanceledException e) { return null; } catch (IOException e) { GithubNotifications.showError(project, CANNOT_CREATE_PULL_REQUEST, e); return null; } return new GithubCreatePullRequestWorker( project, git, gitRepository, path, remoteName, remoteUrl, currentBranch.getName(), auth); }
/** * Setup remotes combobox. The default remote for the current branch is selected by default. This * method gets current branch for the project. * * @param project the project * @param root the git root * @param remoteCombobox the combobox to update * @param fetchUrl if true, the fetch url is shown instead of push url */ public static void setupRemotes( final Project project, final VirtualFile root, final JComboBox remoteCombobox, final boolean fetchUrl) { final GitRepository repo = GitRepositoryManager.getInstance(project).getRepositoryForRoot(root); assert repo != null : "GitRepository can't be null for root " + root; GitBranch gitBranch = repo.getCurrentBranch(); final String branch = gitBranch != null ? gitBranch.getName() : null; setupRemotes(project, root, branch, remoteCombobox, fetchUrl); }
private String makeDescription() { String currentBranchOrRev; boolean onBranch; if (myRepositories.size() > 1) { LOG.assertTrue(myBaseBranch != null, "Branches have unexpectedly diverged"); currentBranchOrRev = myBaseBranch; onBranch = true; } else { GitRepository repository = myInitialRepository; if (repository.isOnBranch()) { GitBranch currentBranch = repository.getCurrentBranch(); assert currentBranch != null; currentBranchOrRev = currentBranch.getName(); onBranch = true; } else { currentBranchOrRev = repository.getCurrentRevision(); onBranch = false; } } StringBuilder description = new StringBuilder(); if (onBranch) { description.append( GitBundle.message( "branch.delete.not_fully_merged.description", myBranchToDelete, myBaseBranch)); } else { description.append( GitBundle.message( "branch.delete.not_fully_merged.description.not_on_branch", myBranchToDelete, currentBranchOrRev, myBaseBranch)); } if (!myMergedToBranches.isEmpty()) { String listOfMergedBranches = StringUtil.join( StringUtil.surround(ArrayUtil.toStringArray(myMergedToBranches), "<b>", "</b>"), ", "); description.append("<br>"); if (myMergedToBranches.size() == 1) { description.append( GitBundle.message( "branch.delete.merged_to.one", myBranchToDelete, listOfMergedBranches)); } else { description.append( GitBundle.message( "branch.delete.merged_to.many", myBranchToDelete, listOfMergedBranches)); } } description.append("<br>").append(GitBundle.message("branch.delete.warning", myBranchToDelete)); return description.toString(); }
/** * For each root check that the repository is on branch, and this branch is tracking a remote * branch, and the remote branch exists. If it is not true for at least one of roots, notify and * return false. If branch configuration is OK for all roots, return true. */ private boolean checkTrackedBranchesConfigured() { LOG.info("checking tracked branch configuration..."); for (GitRepository repository : myRepositories) { VirtualFile root = repository.getRoot(); final GitLocalBranch branch = repository.getCurrentBranch(); if (branch == null) { LOG.info("checkTrackedBranchesConfigured: current branch is null in " + repository); notifyImportantError( myProject, "Can't update: no current branch", "You are in 'detached HEAD' state, which means that you're not on any branch" + rootStringIfNeeded(root) + "Checkout a branch to make update possible."); return false; } GitBranchTrackInfo trackInfo = GitBranchUtil.getTrackInfoForBranch(repository, branch); if (trackInfo == null) { final String branchName = branch.getName(); LOG.info( String.format( "checkTrackedBranchesConfigured: no track info for current branch %s in %s", branch, repository)); String recommendedCommand = String.format( GitVersionSpecialty.KNOWS_SET_UPSTREAM_TO.existsIn(repository.getVcs().getVersion()) ? "git branch --set-upstream-to origin/%1$s %1$s" : "git branch --set-upstream %1$s origin/%1$s", branchName); notifyImportantError( myProject, "Can't update: no tracked branch", "No tracked branch configured for branch " + code(branchName) + rootStringIfNeeded(root) + "To make your branch track a remote branch call, for example,<br/>" + "<code>" + recommendedCommand + "</code>"); return false; } myTrackedBranches.put(root, new GitBranchPair(branch, trackInfo.getRemoteBranch())); } return true; }
private static List<String> getBranchNamesExceptCurrent(GitRepository repository) { List<GitBranch> localBranches = new ArrayList<GitBranch>(repository.getBranches().getLocalBranches()); Collections.sort(localBranches); List<GitBranch> remoteBranches = new ArrayList<GitBranch>(repository.getBranches().getRemoteBranches()); Collections.sort(remoteBranches); if (repository.isOnBranch()) { localBranches.remove(repository.getCurrentBranch()); } final List<String> branchNames = new ArrayList<String>(); for (GitBranch branch : localBranches) { branchNames.add(branch.getName()); } for (GitBranch branch : remoteBranches) { branchNames.add(branch.getName()); } return branchNames; }
@Override public void actionPerformed(final AnActionEvent event) { final Project project = event.getProject(); assert project != null; final VirtualFile file = getAffectedFile(event); GitRepositoryManager manager = GitUtil.getRepositoryManager(project); GitRepository repository = manager.getRepositoryForFile(file); assert repository != null; GitBranch currentBranch = repository.getCurrentBranch(); final String head; if (currentBranch == null) { String currentRevision = repository.getCurrentRevision(); LOG.assertTrue( currentRevision != null, "Current revision is null for " + repository + ". Compare with branch shouldn't be available for fresh repository"); head = DvcsUtil.getShortHash(currentRevision); } else { head = currentBranch.getName(); } final List<String> branchNames = getBranchNamesExceptCurrent(repository); // prepare and invoke popup final JBList list = new JBList(branchNames); JBPopupFactory.getInstance() .createListPopupBuilder(list) .setTitle("Select branch to compare") .setItemChoosenCallback(new OnBranchChooseRunnable(project, file, head, list)) .setAutoselectOnMouseMove(true) .createPopup() .showInBestPositionFor(event.getDataContext()); }