Action Reactoring (AbstractOperationAction)
[egit.git] / org.eclipse.egit.core / src / org / eclipse / egit / core / op / AddToIndexOperation.java
blob95ab51f6c1a68a2a0984d103fe699b2580773e92
1 /*******************************************************************************
2 * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com>
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9 package org.eclipse.egit.core.op;
11 import java.io.File;
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.IdentityHashMap;
17 import org.eclipse.core.resources.IFile;
18 import org.eclipse.core.resources.IProject;
19 import org.eclipse.core.resources.IResource;
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.core.runtime.IAdaptable;
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.core.runtime.NullProgressMonitor;
24 import org.eclipse.core.runtime.jobs.ISchedulingRule;
25 import org.eclipse.core.runtime.jobs.MultiRule;
26 import org.eclipse.egit.core.Activator;
27 import org.eclipse.egit.core.CoreText;
28 import org.eclipse.egit.core.project.RepositoryMapping;
29 import org.eclipse.jgit.lib.GitIndex;
30 import org.eclipse.jgit.lib.Repository;
31 import org.eclipse.jgit.lib.GitIndex.Entry;
33 /**
35 public class AddToIndexOperation implements IEGitOperation {
36 private final Collection<IResource> rsrcList;
37 private final Collection<IFile> notAddedFiles;
39 private final IdentityHashMap<RepositoryMapping, Object> mappings;
41 /**
42 * Create a new operation to add files to the Git index
44 * @param rsrcs
45 * collection of {@link IResource}s which should be added to the
46 * relevant Git repositories.
48 public AddToIndexOperation(final Collection<IResource> rsrcs) {
49 rsrcList = rsrcs;
50 mappings = new IdentityHashMap<RepositoryMapping, Object>();
51 notAddedFiles = new ArrayList<IFile>();
54 /* (non-Javadoc)
55 * @see org.eclipse.egit.core.op.IEGitOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
57 public void execute(IProgressMonitor m) throws CoreException {
58 IProgressMonitor monitor;
59 if (m == null)
60 monitor = new NullProgressMonitor();
61 else
62 monitor = m;
63 Collection<GitIndex> changedIndexes = new ArrayList<GitIndex>();
64 // GitIndex can not be updated if it contains staged entries
65 Collection<GitIndex> indexesWithStagedEntries = new ArrayList<GitIndex>();
66 try {
67 for (Object obj : rsrcList) {
68 obj = ((IAdaptable) obj).getAdapter(IResource.class);
69 if (obj instanceof IFile)
70 addToIndex((IFile) obj, changedIndexes,
71 indexesWithStagedEntries);
72 monitor.worked(200);
74 if (!changedIndexes.isEmpty()) {
75 for (GitIndex idx : changedIndexes) {
76 idx.write();
80 } catch (RuntimeException e) {
81 throw new CoreException(Activator.error(CoreText.AddToIndexOperation_failed, e));
82 } catch (IOException e) {
83 throw new CoreException(Activator.error(CoreText.AddToIndexOperation_failed, e));
84 } finally {
85 for (final RepositoryMapping rm : mappings.keySet())
86 rm.fireRepositoryChanged();
87 mappings.clear();
88 monitor.done();
92 /* (non-Javadoc)
93 * @see org.eclipse.egit.core.op.IEGitOperation#getSchedulingRule()
95 public ISchedulingRule getSchedulingRule() {
96 return new MultiRule(rsrcList.toArray(new IResource[rsrcList.size()]));
99 /**
100 * @return returns the files that could not be added to the index
101 * because there are unmerged entries
103 public Collection<IFile> getNotAddedFiles() {
104 return notAddedFiles;
107 private void addToIndex(IFile file,
108 Collection<GitIndex> changedIndexes,
109 Collection<GitIndex> indexesWithUnmergedEntries) throws IOException {
110 IProject project = file.getProject();
111 RepositoryMapping map = RepositoryMapping.getMapping(project);
112 Repository repo = map.getRepository();
113 GitIndex index = null;
114 index = repo.getIndex();
115 Entry entry = index.getEntry(map.getRepoRelativePath(file));
116 if (entry == null)
117 return;
118 if (indexesWithUnmergedEntries.contains(index)) {
119 notAddedFiles.add(file);
120 return;
121 } else {
122 if (!canUpdateIndex(index)) {
123 indexesWithUnmergedEntries.add(index);
124 notAddedFiles.add(file);
125 return;
128 if (entry.isModified(map.getWorkDir())) {
129 entry.update(new File(map.getWorkDir(), entry.getName()));
130 if (!changedIndexes.contains(index))
131 changedIndexes.add(index);
136 * The method checks if the given index can be updated. The index can be
137 * updated if it does not contain entries with stage !=0.
139 * @param index
140 * @return true if the given index can be updated
142 private static boolean canUpdateIndex(GitIndex index) {
143 Entry[] members = index.getMembers();
144 for (int i = 0; i < members.length; i++) {
145 if (members[i].getStage() != 0)
146 return false;
148 return true;