1 /*******************************************************************************
2 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2008, Google Inc.
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *******************************************************************************/
11 package org
.eclipse
.egit
.core
.project
;
14 import java
.io
.IOException
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Arrays
;
17 import java
.util
.Collection
;
18 import java
.util
.HashSet
;
21 import org
.eclipse
.core
.resources
.IContainer
;
22 import org
.eclipse
.core
.resources
.IProject
;
23 import org
.eclipse
.core
.resources
.IResource
;
24 import org
.eclipse
.core
.runtime
.CoreException
;
25 import org
.eclipse
.core
.runtime
.IPath
;
26 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
27 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
28 import org
.eclipse
.core
.runtime
.SubProgressMonitor
;
29 import org
.eclipse
.egit
.core
.CoreText
;
30 import org
.eclipse
.egit
.core
.internal
.trace
.GitTraceLocation
;
31 import org
.eclipse
.jgit
.lib
.Constants
;
32 import org
.eclipse
.jgit
.util
.SystemReader
;
35 * Searches for existing Git repositories associated with a project's files.
37 * This finder algorithm searches a project's contained files to see if any of
38 * them are located within the working directory of an existing Git repository.
39 * The finder searches through linked resources, as the EGit core is capable of
40 * dealing with linked directories spanning multiple repositories in the same
44 * The search algorithm is exhaustive, it will find all matching repositories.
45 * For the project itself as well as for each linked container within the
46 * project it scans down the local filesystem trees to locate any Git
47 * repositories which may be found there. It also scans up the local filesystem
48 * tree to locate any Git repository which may be outside of Eclipse's
49 * workspace-view of the world, but which contains the project or a linked
50 * resource within the project. In short, if there is a Git repository
51 * associated, it finds it.
54 public class RepositoryFinder
{
55 private final IProject proj
;
57 private final Collection
<RepositoryMapping
> results
= new ArrayList
<RepositoryMapping
>();
58 private final Set
<File
> gitdirs
= new HashSet
<File
>();
60 private Set
<String
> ceilingDirectories
= new HashSet
<String
>();
63 * Create a new finder to locate Git repositories for a project.
66 * the project this new finder should locate the existing Git
69 public RepositoryFinder(final IProject p
) {
71 String ceilingDirectoriesVar
= SystemReader
.getInstance().getenv(
72 Constants
.GIT_CEILING_DIRECTORIES_KEY
);
73 if (ceilingDirectoriesVar
!= null) {
74 ceilingDirectories
.addAll(Arrays
.asList(ceilingDirectoriesVar
75 .split(File
.pathSeparator
)));
80 * Run the search algorithm.
83 * a progress monitor to report feedback to; may be null.
84 * @return all found {@link RepositoryMapping} instances associated with the
85 * project supplied to this instance's constructor.
86 * @throws CoreException
87 * Eclipse was unable to access its workspace, and threw up on
88 * us. We're throwing it back at the caller.
90 public Collection
<RepositoryMapping
> find(IProgressMonitor m
) throws CoreException
{
92 m
= new NullProgressMonitor();
98 private void find(final IProgressMonitor m
, final IContainer c
)
99 throws CoreException
{
100 final IPath loc
= c
.getLocation();
102 m
.beginTask("", 101); //$NON-NLS-1$
103 m
.subTask(CoreText
.RepositoryFinder_finding
);
106 final File fsLoc
= loc
.toFile();
107 assert fsLoc
.isAbsolute();
108 final File ownCfg
= configFor(fsLoc
);
109 final IResource
[] children
;
111 if (ownCfg
.isFile()) {
112 register(c
, ownCfg
.getParentFile());
114 if (c
.isLinked() || c
instanceof IProject
) {
115 File p
= fsLoc
.getParentFile();
117 // TODO is this the right location?
118 if (GitTraceLocation
.CORE
.isActive())
119 GitTraceLocation
.getTrace().trace(
120 GitTraceLocation
.CORE
.getLocation(),
121 "Looking at candidate dir: " //$NON-NLS-1$
123 final File pCfg
= configFor(p
);
125 register(c
, pCfg
.getParentFile());
127 if (ceilingDirectories
.contains(p
.getPath()))
129 p
= p
.getParentFile();
134 children
= c
.members();
135 if (children
!= null && children
.length
> 0) {
136 final int scale
= 100 / children
.length
;
137 for (int k
= 0; k
< children
.length
; k
++) {
138 final IResource o
= children
[k
];
139 if (o
instanceof IContainer
140 && !o
.getName().equals(Constants
.DOT_GIT
)) {
141 find(new SubProgressMonitor(m
, scale
),
154 private File
configFor(final File fsLoc
) {
155 return new File(new File(fsLoc
, Constants
.DOT_GIT
),
156 "config"); //$NON-NLS-1$
159 private void register(final IContainer c
, final File gitdir
) {
162 f
= gitdir
.getCanonicalFile();
163 } catch (IOException ioe
) {
164 f
= gitdir
.getAbsoluteFile();
166 if (gitdirs
.contains(f
))
169 results
.add(new RepositoryMapping(c
, f
));