Merge commit 'a7e928daaf7ba4176b5044797f90b21f420ab2f7'
* commit 'a7e928daaf7ba4176b5044797f90b21f420ab2f7': Verify the case of the project name before opening git repository
This commit is contained in:
@@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user