/*******************************************************************************
 * Copyright (c) 2008 VecTrace (Zingo Andersen) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Jerome Negre              - implementation
 *     Bastian Doetsch           - added authentication to push
 *     Andrei Loskutov (Intland) - bug fixes
 *******************************************************************************/
package com.vectrace.MercurialEclipse.commands;

import java.net.URI;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;

import com.vectrace.MercurialEclipse.exception.HgException;
import com.vectrace.MercurialEclipse.model.ChangeSet;
import com.vectrace.MercurialEclipse.model.HgRoot;
import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants;
import com.vectrace.MercurialEclipse.storage.HgRepositoryLocation;
import com.vectrace.MercurialEclipse.team.cache.RefreshJob;
import com.vectrace.MercurialEclipse.utils.ResourceUtils;

public class HgPushPullClient extends AbstractClient {

	public static String push(HgRoot hgRoot, HgRepositoryLocation repo,
			boolean force, String revision, int timeout) throws HgException {
		AbstractShellCommand command = new HgCommand("push", hgRoot, true); //$NON-NLS-1$
		command.setUsePreferenceTimeout(MercurialPreferenceConstants.PUSH_TIMEOUT);

		if (force) {
			command.addOptions("-f"); //$NON-NLS-1$
		}

		if (revision != null && revision.length() > 0) {
			command.addOptions("-r", revision.trim()); //$NON-NLS-1$
		}

		addRepoToHgCommand(repo, command);
		return new String(command.executeToBytes(timeout));
	}



	public static String pull(HgRoot hgRoot,
			HgRepositoryLocation location, boolean update) throws HgException {
		return pull(hgRoot, null, location, update, false, false, false);
	}

	public static String pull(HgRoot hgRoot, ChangeSet changeset,
			HgRepositoryLocation repo, boolean update, boolean rebase,
			boolean force, boolean timeout) throws HgException {

		URI uri = repo.getUri();
		String pullSource;
		if (uri != null) {
			pullSource = uri.toASCIIString();
		} else {
			pullSource = repo.getLocation();
		}

		return pull(hgRoot, changeset, pullSource, update, rebase, force, timeout);
	}

	public static String pull(final HgRoot hgRoot, ChangeSet changeset,
			String pullSource, boolean update, boolean rebase,
			boolean force, boolean timeout) throws HgException {

		HgCommand command = new HgCommand("pull", hgRoot, true); //$NON-NLS-1$

		if (update) {
			command.addOptions("--update"); //$NON-NLS-1$
		} else if (rebase) {
			command.addOptions("--config", "extensions.hgext.rebase="); //$NON-NLS-1$ //$NON-NLS-2$
			command.addOptions("--rebase"); //$NON-NLS-1$
		}

		if (force) {
			command.addOptions("--force"); //$NON-NLS-1$
		}
		if (changeset != null) {
			command.addOptions("--rev", changeset.getChangeset()); //$NON-NLS-1$
		}

		command.addOptions(pullSource);

		String result;
		if (timeout) {
			command.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT);
			result = new String(command.executeToBytes());
		} else {
			result = new String(command.executeToBytes(Integer.MAX_VALUE));
		}
		// The reason to use "all" instead of only "local + incoming", is that we can pull
		// from another repo as the sync clients for given project may use
		// in this case, we also need to update "outgoing" changesets
		final int flags = RefreshJob.ALL;
		Set<IProject> projects = ResourceUtils.getProjects(command.getHgRoot());
		for (final IProject iProject : projects) {
			if(update) {
				RefreshWorkspaceStatusJob job = new RefreshWorkspaceStatusJob(iProject);
				job.addJobChangeListener(new JobChangeAdapter(){
				@Override
					public void done(IJobChangeEvent event) {
						new RefreshJob("Refreshing " + iProject.getName(), iProject, flags).schedule();
					}
				});
				job.schedule();
			} else {
				new RefreshJob("Refreshing " + iProject.getName(), iProject, flags).schedule();
			}
		}
		return result;
	}
}

@@ -3251,16 +3251,91 @@
 urce);%0A%0A
+%09%09Set%3CIProject%3E projects = ResourceUtils.getProjects(command.getHgRoot());%0A
 %09%09String
@@ -3343,16 +3343,25 @@
 result;%0A
+%09%09try %7B%0A%09
 %09%09if (ti
@@ -3365,24 +3365,25 @@
 (timeout) %7B%0A
+%09
 %09%09%09command.s
@@ -3449,16 +3449,17 @@
 MEOUT);%0A
+%09
 %09%09%09resul
@@ -3498,24 +3498,25 @@
 Bytes());%0A%09%09
+%09
 %7D else %7B%0A%09%09%09
@@ -3512,16 +3512,17 @@
  else %7B%0A
+%09
 %09%09%09resul
@@ -3580,20 +3580,335 @@
 ALUE));%0A
+%09
 %09%09%7D%0A
+%09%09%7D finally %7B%0A%09%09%09// doesn't metter how far we was: we have to trigger update of caches in case%0A%09%09%09// the pull was *partly* successfull (e.g. pull was ok, but update not)%0A%09%09%09refreshProjects(update, projects);%0A%09%09%7D%0A%09%09return result;%0A%09%7D%0A%0A%0A%0A%09private static void refreshProjects(boolean update, Set%3CIProject%3E projects) %7B%0A
 %09%09// The
@@ -4157,83 +4157,8 @@
 LL;%0A
-%09%09Set%3CIProject%3E projects = ResourceUtils.getProjects(command.getHgRoot());%0A
 %09%09fo
@@ -4631,30 +4631,13 @@
 %09%09%7D%0A%09%09%7D%0A
-%09%09return result;%0A
 %09%7D%0A%7D%0A

Fix for not refreshing the cache after pertly successful "pull + update" operation (pull was ok, but update not)