Merge commit 'a7e928daaf7ba4176b5044797f90b21f420ab2f7'

* commit 'a7e928daaf7ba4176b5044797f90b21f420ab2f7':
  Verify the case of the project name before opening git repository
This commit is contained in:
Shawn O. Pearce
2011-10-27 09:50:53 -07:00
3 changed files with 128 additions and 43 deletions

View File

@@ -100,8 +100,13 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
throw new RepositoryNotFoundException("Invalid name: " + name); throw new RepositoryNotFoundException("Invalid name: " + name);
} }
final FileKey loc = FileKey.lenient(gitDirOf(name), FS.DETECTED);
if (!getProjectName(loc.getFile()).equals(name)) {
throw new RepositoryNotFoundException(gitDirOf(name));
}
try { try {
final FileKey loc = FileKey.lenient(gitDirOf(name), FS.DETECTED);
return RepositoryCache.open(loc); return RepositoryCache.open(loc);
} catch (IOException e1) { } catch (IOException e1) {
final RepositoryNotFoundException e2; final RepositoryNotFoundException e2;
@@ -117,24 +122,30 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
throw new RepositoryNotFoundException("Invalid name: " + name); throw new RepositoryNotFoundException("Invalid name: " + name);
} }
try { File dir = FileKey.resolve(gitDirOf(name), FS.DETECTED);
File dir = FileKey.resolve(gitDirOf(name), FS.DETECTED); FileKey loc;
FileKey loc; if (dir != null) {
if (dir != null) { // Already exists on disk, use the repository we found.
// Already exists on disk, use the repository we found. //
// loc = FileKey.exact(dir, FS.DETECTED);
loc = FileKey.exact(dir, FS.DETECTED);
} else {
// It doesn't exist under any of the standard permutations
// of the repository name, so prefer the standard bare name.
//
String n = name.get();
if (!n.endsWith(Constants.DOT_GIT_EXT)) {
n = n + Constants.DOT_GIT_EXT;
}
loc = FileKey.exact(new File(basePath, n), FS.DETECTED);
}
final Project.NameKey nameOfExistingProject =
getProjectName(loc.getFile());
if (!nameOfExistingProject.equals(name)) {
throw new RepositoryCaseMismatchException(name, nameOfExistingProject);
}
} else {
// It doesn't exist under any of the standard permutations
// of the repository name, so prefer the standard bare name.
//
String n = name.get();
if (!n.endsWith(Constants.DOT_GIT_EXT)) {
n = n + Constants.DOT_GIT_EXT;
}
loc = FileKey.exact(new File(basePath, n), FS.DETECTED);
}
try {
Repository db = RepositoryCache.open(loc, false); Repository db = RepositoryCache.open(loc, false);
db.create(true /* bare */); db.create(true /* bare */);
@@ -256,19 +267,7 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
for (File f : ls) { for (File f : ls) {
String fileName = f.getName(); String fileName = f.getName();
if (FileKey.isGitRepository(f, FS.DETECTED)) { if (FileKey.isGitRepository(f, FS.DETECTED)) {
String projectName; Project.NameKey nameKey = getProjectName(prefix, fileName);
if (fileName.equals(Constants.DOT_GIT)) {
projectName = prefix.substring(0, prefix.length() - 1);
} else if (fileName.endsWith(Constants.DOT_GIT_EXT)) {
int newLen = fileName.length() - Constants.DOT_GIT_EXT.length();
projectName = prefix + fileName.substring(0, newLen);
} else {
projectName = prefix + fileName;
}
Project.NameKey nameKey = new Project.NameKey(projectName);
if (isUnreasonableName(nameKey)) { if (isUnreasonableName(nameKey)) {
log.warn("Ignoring unreasonably named repository " + f.getAbsolutePath()); log.warn("Ignoring unreasonably named repository " + f.getAbsolutePath());
} else { } else {
@@ -280,4 +279,30 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
} }
} }
} }
private Project.NameKey getProjectName(final String prefix,
final String fileName) {
final String projectName;
if (fileName.equals(Constants.DOT_GIT)) {
projectName = prefix.substring(0, prefix.length() - 1);
} else if (fileName.endsWith(Constants.DOT_GIT_EXT)) {
int newLen = fileName.length() - Constants.DOT_GIT_EXT.length();
projectName = prefix + fileName.substring(0, newLen);
} else {
projectName = prefix + fileName;
}
return new Project.NameKey(projectName);
}
private Project.NameKey getProjectName(final File gitDir) {
final String relativeGitPath =
getBasePath().toURI().relativize(gitDir.toURI()).getPath();
final String prefix =
relativeGitPath.substring(0, relativeGitPath.length() - 1
- gitDir.getName().length());
return getProjectName(prefix, gitDir.getName());
}
} }

View File

@@ -0,0 +1,51 @@
// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.git;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.Project.NameKey;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
/**
* This exception is thrown if a project cannot be created because a project
* with the same name in a different case already exists. This can only happen
* if the OS has a case insensitive file system (e.g. Windows), because in this
* case the name for the git repository in the file system is already occupied
* by the existing project.
*/
public class RepositoryCaseMismatchException extends
RepositoryNotFoundException {
private static final long serialVersionUID = 1L;
private final NameKey nameOfExistingProject;
/**
* @param projectName name of the project that cannot be created
* @param nameOfExistingProject name of the project that already exists and
* occupies the name for the git repository in the file system
*/
public RepositoryCaseMismatchException(final Project.NameKey projectName,
final Project.NameKey nameOfExistingProject) {
super("Name occupied in other case: " + projectName.get() + "; project "
+ nameOfExistingProject.get() + " exists");
this.nameOfExistingProject = nameOfExistingProject;
}
public NameKey getNameOfExistingProject() {
return nameOfExistingProject;
}
}

View File

@@ -29,6 +29,7 @@ import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate; import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.ReplicationQueue; import com.google.gerrit.server.git.ReplicationQueue;
import com.google.gerrit.server.git.RepositoryCaseMismatchException;
import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectControl; import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.sshd.BaseCommand; import com.google.gerrit.sshd.BaseCommand;
@@ -178,18 +179,9 @@ final class CreateProject extends BaseCommand {
repo.close(); repo.close();
} }
} catch (IllegalStateException err) { } catch (IllegalStateException err) {
try { handleRepositoryExistsException(nameKey);
Repository repo = repoManager.openRepository(nameKey); } catch (RepositoryCaseMismatchException err) {
try { handleRepositoryExistsException(err.getNameOfExistingProject());
if (repo.getObjectDatabase().exists()) {
throw new UnloggedFailure(1, "fatal: project \"" + projectName + "\" exists");
}
} finally {
repo.close();
}
} catch (RepositoryNotFoundException doesNotExist) {
throw new Failure(1, "fatal: Cannot create " + projectName, err);
}
} catch (RepositoryNotFoundException badName) { } catch (RepositoryNotFoundException badName) {
throw new UnloggedFailure(1, "fatal: " + badName.getMessage()); throw new UnloggedFailure(1, "fatal: " + badName.getMessage());
} catch (Exception err) { } catch (Exception err) {
@@ -297,4 +289,21 @@ final class CreateProject extends BaseCommand {
throw new Failure(1, "--branch \"" + branch + "\" is not a valid name"); throw new Failure(1, "--branch \"" + branch + "\" is not a valid name");
} }
} }
private void handleRepositoryExistsException(final Project.NameKey projectName)
throws Failure {
try {
Repository repo = repoManager.openRepository(projectName);
try {
if (repo.getObjectDatabase().exists()) {
throw new UnloggedFailure(1, "fatal: project \"" + projectName
+ "\" exists");
}
} finally {
repo.close();
}
} catch (RepositoryNotFoundException err) {
throw new Failure(1, "fatal: Cannot create " + projectName, err);
}
}
} }