tikhomirov@529: /* tikhomirov@529: * Copyright (c) 2013 TMate Software Ltd tikhomirov@529: * tikhomirov@529: * This program is free software; you can redistribute it and/or modify tikhomirov@529: * it under the terms of the GNU General Public License as published by tikhomirov@529: * the Free Software Foundation; version 2 of the License. tikhomirov@529: * tikhomirov@529: * This program is distributed in the hope that it will be useful, tikhomirov@529: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@529: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@529: * GNU General Public License for more details. tikhomirov@529: * tikhomirov@529: * For information on how to redistribute this software under tikhomirov@529: * the terms of a license other than GNU General Public License tikhomirov@529: * contact TMate Software at support@hg4j.com tikhomirov@529: */ tikhomirov@529: package org.tmatesoft.hg.core; tikhomirov@529: tikhomirov@529: import java.util.LinkedHashSet; tikhomirov@529: tikhomirov@617: import org.tmatesoft.hg.internal.COWTransaction; tikhomirov@529: import org.tmatesoft.hg.internal.DirstateBuilder; tikhomirov@529: import org.tmatesoft.hg.internal.DirstateReader; tikhomirov@529: import org.tmatesoft.hg.internal.Internals; tikhomirov@617: import org.tmatesoft.hg.internal.Transaction; tikhomirov@529: import org.tmatesoft.hg.repo.HgManifest.Flags; tikhomirov@529: import org.tmatesoft.hg.repo.HgRepository; tikhomirov@617: import org.tmatesoft.hg.repo.HgRepositoryLock; tikhomirov@529: import org.tmatesoft.hg.repo.HgRuntimeException; tikhomirov@581: import org.tmatesoft.hg.util.CancelSupport; tikhomirov@581: import org.tmatesoft.hg.util.CancelledException; tikhomirov@529: import org.tmatesoft.hg.util.Path; tikhomirov@581: import org.tmatesoft.hg.util.ProgressSupport; tikhomirov@529: tikhomirov@529: /** tikhomirov@529: * Schedule files for addition and removal tikhomirov@529: * XXX and, perhaps, forget() functionality shall be here as well? tikhomirov@529: * tikhomirov@529: * @since 1.1 tikhomirov@529: * @author Artem Tikhomirov tikhomirov@529: * @author TMate Software Ltd. tikhomirov@529: */ tikhomirov@529: public class HgAddRemoveCommand extends HgAbstractCommand { tikhomirov@529: tikhomirov@529: private final HgRepository repo; tikhomirov@529: private final LinkedHashSet toAdd, toRemove; tikhomirov@529: tikhomirov@529: public HgAddRemoveCommand(HgRepository hgRepo) { tikhomirov@529: repo = hgRepo; tikhomirov@529: toAdd = new LinkedHashSet(); tikhomirov@529: toRemove = new LinkedHashSet(); tikhomirov@529: } tikhomirov@529: tikhomirov@529: /** tikhomirov@529: * Schedule specified files to get listed in dirstate as added tikhomirov@529: * tikhomirov@529: * @param paths files to mark as added, additive tikhomirov@529: * @return this for convenience tikhomirov@529: */ tikhomirov@529: public HgAddRemoveCommand add(Path... paths) { tikhomirov@529: if (paths == null) { tikhomirov@529: throw new IllegalArgumentException(); tikhomirov@529: } tikhomirov@529: for (Path p : paths) { tikhomirov@529: toRemove.remove(p); tikhomirov@529: toAdd.add(p); tikhomirov@529: } tikhomirov@529: return this; tikhomirov@529: } tikhomirov@529: tikhomirov@529: /** tikhomirov@529: * Schedule specified files to be marked as removed tikhomirov@529: * tikhomirov@529: * @param paths files to mark as removed, additive tikhomirov@529: * @return this for convenience tikhomirov@529: */ tikhomirov@529: public HgAddRemoveCommand remove(Path... paths) { tikhomirov@529: if (paths == null) { tikhomirov@529: throw new IllegalArgumentException(); tikhomirov@529: } tikhomirov@529: for (Path p : paths) { tikhomirov@529: toAdd.remove(p); tikhomirov@529: toRemove.add(p); tikhomirov@529: } tikhomirov@529: return this; tikhomirov@529: } tikhomirov@529: tikhomirov@529: public HgAddRemoveCommand addAll() { tikhomirov@529: throw Internals.notImplemented(); tikhomirov@529: } tikhomirov@529: tikhomirov@529: public HgAddRemoveCommand forget(Path path) { tikhomirov@529: throw Internals.notImplemented(); tikhomirov@529: } tikhomirov@529: tikhomirov@529: /** tikhomirov@529: * Perform scheduled addition/removal tikhomirov@529: * tikhomirov@581: * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state tikhomirov@617: * @throws HgRepositoryLockException if failed to lock the repo for modifications tikhomirov@581: * @throws CancelledException if execution of the command was cancelled tikhomirov@529: */ tikhomirov@617: public void execute() throws HgException, HgRepositoryLockException, CancelledException { tikhomirov@617: final HgRepositoryLock wdLock = repo.getWorkingDirLock(); tikhomirov@617: wdLock.acquire(); tikhomirov@529: try { tikhomirov@581: final ProgressSupport progress = getProgressSupport(null); tikhomirov@581: final CancelSupport cancellation = getCancelSupport(null, true); tikhomirov@581: cancellation.checkCancelled(); tikhomirov@581: progress.start(2 + toAdd.size() + toRemove.size()); tikhomirov@529: Internals implRepo = Internals.getInstance(repo); tikhomirov@529: final DirstateBuilder dirstateBuilder = new DirstateBuilder(implRepo); tikhomirov@529: dirstateBuilder.fillFrom(new DirstateReader(implRepo, new Path.SimpleSource())); tikhomirov@581: progress.worked(1); tikhomirov@581: cancellation.checkCancelled(); tikhomirov@529: for (Path p : toAdd) { tikhomirov@529: dirstateBuilder.recordAdded(p, Flags.RegularFile, -1); tikhomirov@581: progress.worked(1); tikhomirov@581: cancellation.checkCancelled(); tikhomirov@529: } tikhomirov@529: for (Path p : toRemove) { tikhomirov@529: dirstateBuilder.recordRemoved(p); tikhomirov@581: progress.worked(1); tikhomirov@581: cancellation.checkCancelled(); tikhomirov@529: } tikhomirov@617: Transaction.Factory trFactory = new COWTransaction.Factory(); tikhomirov@617: Transaction tr = trFactory.create(repo); tikhomirov@617: try { tikhomirov@617: dirstateBuilder.serialize(tr); tikhomirov@617: tr.commit(); tikhomirov@617: } catch (RuntimeException ex) { tikhomirov@617: tr.rollback(); tikhomirov@617: throw ex; tikhomirov@617: } catch (HgException ex) { tikhomirov@617: tr.rollback(); tikhomirov@617: throw ex; tikhomirov@617: } tikhomirov@581: progress.worked(1); tikhomirov@581: progress.done(); tikhomirov@529: } catch (HgRuntimeException ex) { tikhomirov@529: throw new HgLibraryFailureException(ex); tikhomirov@617: } finally { tikhomirov@617: wdLock.release(); tikhomirov@529: } tikhomirov@529: } tikhomirov@529: }