Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 75 additions & 40 deletions ide/git/src/org/netbeans/modules/git/ui/fetch/PullAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.netbeans.modules.git.ui.actions.ActionProgressSupport;
import org.netbeans.modules.git.ui.actions.GitAction;
import org.netbeans.modules.git.ui.actions.SingleRepositoryAction;
import org.netbeans.modules.git.ui.branch.SetTrackingAction;
import org.netbeans.modules.git.ui.merge.MergeRevisionAction;
import org.netbeans.modules.git.ui.output.OutputLogger;
import org.netbeans.modules.git.ui.rebase.RebaseAction;
Expand All @@ -65,6 +66,7 @@
import org.openide.awt.ActionRegistration;
import org.openide.awt.Mnemonics;
import org.openide.util.NbBundle;
import org.openide.util.actions.SystemAction;

/**
*
Expand Down Expand Up @@ -107,6 +109,10 @@ public void run () {
}

private void pull (final File repository) {
pull(repository, null);
}

public void pull (final File repository, final GitBranch branchToSelect) {
RepositoryInfo info = RepositoryInfo.getInstance(repository);
try {
info.refreshRemotes();
Expand All @@ -117,7 +123,7 @@ private void pull (final File repository) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run () {
PullWizard wiz = new PullWizard(repository, remotes);
PullWizard wiz = new PullWizard(repository, remotes, branchToSelect);
if (wiz.show()) {
Utils.logVCSExternalRepository("GIT", wiz.getFetchUri()); //NOI18N
pull(repository, wiz.getFetchUri(), wiz.getFetchRefSpecs(), wiz.getBranchToMerge(), wiz.getRemoteToPersist());
Expand All @@ -144,6 +150,7 @@ private static class GitProgressSupportImpl extends GitProgressSupport {
private final String branchToMerge;
private final String target;
private final String remoteNameToUpdate;
private boolean pullSuccessful = false;

public GitProgressSupportImpl (List<String> fetchRefSpecs, String branchToMerge, String target, String remoteNameToUpdate) {
this.fetchRefSpecs = fetchRefSpecs;
Expand Down Expand Up @@ -182,55 +189,71 @@ protected void perform () {
return;
}
}
GitUtils.runWithoutIndexing(new Callable<Void>() {
@Override
public Void call () throws Exception {
for (String branch : toDelete) {
client.deleteBranch(branch, true, getProgressMonitor());
getLogger().outputLine(Bundle.MSG_PullAction_branchDeleted(branch));
}
setDisplayName(Bundle.MSG_PullAction_fetching());
Map<String, GitTransportUpdate> fetchResult = FetchAction.fetchRepeatedly(
client, getProgressMonitor(), target, fetchRefSpecs);
if (isCanceled()) {
return null;
GitUtils.runWithoutIndexing(() -> {
for (String branch : toDelete) {
client.deleteBranch(branch, true, getProgressMonitor());
getLogger().outputLine(Bundle.MSG_PullAction_branchDeleted(branch));
}
setDisplayName(Bundle.MSG_PullAction_fetching());
Map<String, GitTransportUpdate> fetchResult = FetchAction.fetchRepeatedly(
client, getProgressMonitor(), target, fetchRefSpecs);
if (isCanceled()) {
return null;
}
FetchUtils.log(repository, fetchResult, getLogger());
if (!isCanceled()) {
setDisplayName(Bundle.MSG_PullAction_progress_syncBranches());
FetchUtils.syncTrackingBranches(repository, fetchResult, GitProgressSupportImpl.this, GitProgressSupportImpl.this.getProgress(), false);
}
if (isCanceled() || branchToMerge == null) {
return null;
}
new BranchSynchronizer(branchToMerge, repository, new BranchSynchronizer.GitProgressSupportDelegate() {

@Override
public GitClient getClient () throws GitException {
return client;
}
FetchUtils.log(repository, fetchResult, getLogger());
if (!isCanceled()) {
setDisplayName(Bundle.MSG_PullAction_progress_syncBranches());
FetchUtils.syncTrackingBranches(repository, fetchResult, GitProgressSupportImpl.this, GitProgressSupportImpl.this.getProgress(), false);

@Override
public OutputLogger getLogger () {
return GitProgressSupportImpl.this.getLogger();
}
if (isCanceled() || branchToMerge == null) {
return null;

@Override
public ProgressDelegate getProgress () {
return GitProgressSupportImpl.this.getProgress();
}
new BranchSynchronizer(branchToMerge, repository, new BranchSynchronizer.GitProgressSupportDelegate() {

@Override
public GitClient getClient () throws GitException {
return client;
}

@Override
public OutputLogger getLogger () {
return GitProgressSupportImpl.this.getLogger();
}

@Override
public ProgressDelegate getProgress () {
return GitProgressSupportImpl.this.getProgress();
}

}).execute();
return null;

}).execute();

if (!isCanceled()) {
pullSuccessful = true;
}
}, repository);

return null;
}, repository);
} catch (GitException ex) {
setError(true);
GitClientExceptionHandler.notifyException(ex, true);
} finally {
setDisplayName(NbBundle.getMessage(GitAction.class, "LBL_Progress.RefreshingStatuses")); //NOI18N
Git.getInstance().getFileStatusCache().refreshAllRoots(Collections.<File, Collection<File>>singletonMap(repository, Git.getInstance().getSeenRoots(repository)));
GitUtils.headChanged(repository);

// Check if tracking should be set up after successful pull
if (pullSuccessful && branchToMerge != null) {
RepositoryInfo info = RepositoryInfo.getInstance(repository);
info.refresh();
GitBranch activeBranch = info.getActiveBranch();
if (activeBranch != null && activeBranch.getTrackedBranch() == null) {
// branchToMerge is the remote branch name (e.g., "origin/master")
if (shallSetupTracking(activeBranch, branchToMerge)) {
SystemAction.get(SetTrackingAction.class).setupTrackedBranchImmediately(
repository, activeBranch.getName(), branchToMerge);
}
}
Comment on lines +248 to +255
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I correct in assuming, that this not called on the EDT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is the hint then thx for this. It never gets into the finally block, beause of another thread is cancelling this. The magic happens in GitUtils.java:886.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runWithoutIndexing can't have part in this. It is inside the try-block, so the finally still must be executed (try-block is line 170-236, finally is lines 240-256). I'm not aware of ways to skip execution of a finally block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be, that runWithoutindexing is not part here, but I set breakpoints and see, that only the finally block inside of the runWithoutIndexing is executed, after this , no other finally block is reached. So the inner finally block is reached, the outer not. This is why I'm confused. As said, my assumption is something with different threads?

}
}
}
}
Expand Down Expand Up @@ -378,5 +401,17 @@ public ActionProgress call () throws GitException {
}
}
}


@NbBundle.Messages({
"LBL_Pull.setupTracking=Set Up Remote Tracking?",
"# {0} - remote branch name", "# {1} - branch name", "MSG_Pull.setupTracking=Pulled from \"{0}\".\n"
+ "Do you want to set up branch \"{1}\" to track the remote branch?"
})
private static boolean shallSetupTracking (GitBranch branch, String remoteBranchName) {
return NotifyDescriptor.YES_OPTION == DialogDisplayer.getDefault().notify(new NotifyDescriptor.Confirmation(
Bundle.MSG_Pull_setupTracking(remoteBranchName, branch.getName()),
Bundle.LBL_Pull_setupTracking(),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.QUESTION_MESSAGE));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ public void setRemote (GitRemoteConfig remote) {
}

public void fillRemoteBranches (final Map<String, GitBranch> branches) {
fillRemoteBranches(Collections.<String,GitBranch>emptyMap(), Collections.<String,GitBranch>emptyMap());
fillRemoteBranches(branches, null);
}

public void fillRemoteBranches (final Map<String, GitBranch> branches, final GitBranch branchToSelect) {
fillRemoteBranchesInternal(Collections.<String,GitBranch>emptyMap(), Collections.<String,GitBranch>emptyMap(), null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the intention here to start with an empty list in any case and then update when loading is done? That might be worth a comment.

I was wondering why null is passed here as branchToSelect. That makes only sense to me, if we just want to initialize.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it yes (Maybe I missed a thing, as always. When you pull a branch without upstream, nothing is selected. When you do a pull from upstream, the error came up "no tracked brach specified for local branch....". And if I remove this, nothing is selected anymore on pull from upstrean. It can be, that I need to modify the line 169 - 173.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't get it. line 169-173 can't be reached for the marked case. I mean this call:

        fillRemoteBranchesInternal(Collections.<String,GitBranch>emptyMap(), Collections.<String,GitBranch>emptyMap(), null);

This will basicly execute (the maps are empty, so all loops in fillRemoteBranchesInternal will not execute):

        List<BranchMapping> l = new ArrayList<BranchMapping>(0);
        Set<String> displayedBranches = new HashSet<String>(0);
        this.branches.setBranches(l);
        stateChanged(new ChangeEvent(this));

I read this as "reset the item selector into a clean state".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, at the end, it is just to make everything set to the default. The null value. If the branchToSelect is set, line 175 is reached. Everything else, is for the default behaviour.

new GitProgressSupport.NoOutputLogging() {
@Override
protected void perform () {
Expand All @@ -140,14 +144,14 @@ protected void perform () {
EventQueue.invokeLater(new Runnable () {
@Override
public void run () {
fillRemoteBranches(branches, localBranches);
fillRemoteBranchesInternal(branches, localBranches, branchToSelect);
}
});
}
}.start(Git.getInstance().getRequestProcessor(repository), repository, NbBundle.getMessage(PullBranchesStep.class, "MSG_FetchBranchesPanel.loadingLocalBranches")); //NOI18N
}

private void fillRemoteBranches (Map<String, GitBranch> branches, Map<String, GitBranch> localBranches) {
private void fillRemoteBranchesInternal (Map<String, GitBranch> branches, Map<String, GitBranch> localBranches, GitBranch branchToSelect) {
List<BranchMapping> l = new ArrayList<BranchMapping>(branches.size());
Set<String> displayedBranches = new HashSet<String>(localBranches.size());
for (GitBranch branch : localBranches.values()) {
Expand All @@ -163,9 +167,14 @@ private void fillRemoteBranches (Map<String, GitBranch> branches, Map<String, Gi
GitBranch localBranch = localBranches.get(branchName);
boolean preselected = localBranch != null && (!localBranch.getId().equals(branch.getId()) // is a modification
// or is the tracked branch - should be offered primarily
|| currentBranch != null
&& currentBranch.getTrackedBranch() != null
|| currentBranch != null
&& currentBranch.getTrackedBranch() != null
&& currentBranch.getTrackedBranch().getName().equals(localBranch.getName()));

if (branchToSelect != null && branch.getName().equals(branchToSelect.getName())) {
preselected = true;
}

l.add(new BranchMapping(branch.getName(), branch.getId(), localBranch, remote, preselected));
}
for (GitBranch branch : localBranches.values()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,23 @@ protected void perform () {
Logger.getLogger(FetchFromUpstreamAction.class.getName()).log(Level.INFO, null, ex);
}
String errorLabel = Bundle.LBL_Pull_pullFromUpstreamFailed();
GitBranch trackedBranch = GitUtils.getTrackedBranch(info, errorLabel);
GitBranch activeBranch = info.getActiveBranch();
if (activeBranch == null) {
return;
}
GitBranch trackedBranch = GitUtils.getTrackedBranch(info, null);

// If no tracked branch and multiple remotes, use full pull UI
if (trackedBranch == null && info.getRemotes().size() > 1) {
SystemAction.get(PullAction.class).pull(repository, activeBranch);
return;
}

if (trackedBranch == null) {
return;
}
GitRemoteConfig cfg = FetchUtils.getRemoteConfigForActiveBranch(trackedBranch, info, errorLabel);

GitRemoteConfig cfg = FetchUtils.getRemoteConfigForActiveBranch(trackedBranch, info, errorLabel);
if (cfg == null) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,16 @@ class PullWizard implements ChangeListener {
private PanelsIterator wizardIterator;
private WizardDescriptor wizardDescriptor;
private final File repository;
private final GitBranch branchToSelect;

public PullWizard (File repository, Map<String, GitRemoteConfig> remotes) {
this(repository, remotes, null);
}

public PullWizard (File repository, Map<String, GitRemoteConfig> remotes, GitBranch branchToSelect) {
this.repository = repository;
this.remotes = remotes;
this.branchToSelect = branchToSelect;
}

boolean show () {
Expand Down Expand Up @@ -154,7 +160,7 @@ public synchronized void nextPanel () {
Map<String, GitBranch> remoteBranches = selectUriStep.getRemoteBranches();
pullBranchesStep.setRemote(remote);
if (remoteBranches != null) {
pullBranchesStep.fillRemoteBranches(remoteBranches);
pullBranchesStep.fillRemoteBranches(remoteBranches, branchToSelect);
}
selectUriStep.storeURI();
}
Expand Down
34 changes: 22 additions & 12 deletions ide/git/src/org/netbeans/modules/git/ui/push/PushAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,13 @@ public void push (final File repository, GitRemoteConfig remote, Collection<Push
}

public void push (final File repository) {
push(repository, null);
}

public void push (final File repository, final GitBranch branchToSelect) {
if (EventQueue.isDispatchThread()) {
Utils.post(new Runnable () {
@Override
public void run () {
push(repository);
}
Utils.post(() -> {
push(repository, branchToSelect);
});
return;
}
Expand All @@ -140,7 +141,7 @@ public void run () {
EventQueue.invokeLater(new Runnable() {
@Override
public void run () {
PushWizard wiz = new PushWizard(repository, remotes);
PushWizard wiz = new PushWizard(repository, remotes, branchToSelect);
if (wiz.show()) {
Utils.logVCSExternalRepository("GIT", wiz.getPushUri()); //NOI18N
push(repository, wiz.getPushUri(), wiz.getPushMappings(), wiz.getFetchRefSpecs(), wiz.getRemoteName());
Expand Down Expand Up @@ -325,12 +326,7 @@ protected void logUpdates (File repository, Map<String, GitTransportUpdate> upda
logger.outputLine(Bundle.MSG_PushAction_updates_addBranch(update.getLocalName(),
update.getNewObjectId(), update.getResult()));
if (!remote && update.getNewObjectId() != null) {
int pos = update.getLocalName().indexOf('/');
if (pos >= 0 && update.getLocalName().substring(pos + 1).equals(currBranch.getName())) {
if (shallSetupTracking(currBranch, update.getLocalName())) {
SystemAction.get(SetTrackingAction.class).setupTrackedBranchImmediately(repository, currBranch.getName(), update.getLocalName());
}
}
callSetTrackingAction(update, currBranch, repository);
}
} else {
logger.outputLine(Bundle.MSG_PushAction_updates_updateBranch(update.getRemoteName(),
Expand All @@ -344,6 +340,11 @@ protected void logUpdates (File repository, Map<String, GitTransportUpdate> upda
update.getOldObjectId(), update.getNewObjectId(), logger);
}
}

// Check if tracking should be set up for updated branches without tracking
if (!remote && update.getNewObjectId() != null && currBranch.getTrackedBranch() == null) {
callSetTrackingAction(update, currBranch, repository);
}
}
} else {
//tag deleting or updating
Expand All @@ -364,6 +365,15 @@ protected void logUpdates (File repository, Map<String, GitTransportUpdate> upda
}
}
}

private void callSetTrackingAction(GitTransportUpdate update, GitBranch currBranch, File repository1) {
int pos = update.getLocalName().indexOf('/');
if (pos >= 0 && update.getLocalName().substring(pos + 1).equals(currBranch.getName())) {
if (shallSetupTracking(currBranch, update.getLocalName())) {
SystemAction.get(SetTrackingAction.class).setupTrackedBranchImmediately(repository1, currBranch.getName(), update.getLocalName());
}
}
}

private void logTrackingUpdate (GitBranch b) {
if (b != null && b.getTrackedBranch() != null) {
Expand Down
17 changes: 17 additions & 0 deletions ide/git/src/org/netbeans/modules/git/ui/push/PushBranchesStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ public HelpCtx getHelp() {
*/
public void fillRemoteBranches (final GitRemoteConfig cfg, final Map<String, GitBranch> branches,
final Map<String, String> tags) {
fillRemoteBranches(cfg, branches, tags, null);
}

/**
*
* @param cfg configuration of the remote repository including URLs of remote
* @param branches list of all branches in the remote repo
* @param tags list of all tags in the remote repo
* @param branchToSelect branch that should be preselected in the list
*/
public void fillRemoteBranches (final GitRemoteConfig cfg, final Map<String, GitBranch> branches,
final Map<String, String> tags, final GitBranch branchToSelect) {
fillLocalObjects(Collections.<PushMapping>emptyList());
new GitProgressSupport.NoOutputLogging() {
@Override
Expand Down Expand Up @@ -162,6 +174,11 @@ protected void perform () {
}
boolean preselected = !conflicted && updateNeeded;

// If a specific branch should be selected, override preselection
if (branchToSelect != null && branch.getName().equals(branchToSelect.getName())) {
preselected = true;
}

//add current branch in the list for update or for adding
l.add(new PushMapping.PushBranchMapping(remoteBranch == null ? null : remoteBranch.getName(),
remoteBranch == null ? null : remoteBranch.getId(),
Expand Down
Loading
Loading