Use Project.NameKey in GitRepositoryManager
This simplifies all of the calling sites, where they have a Project.NameKey on hand and would prefer not to invoke .get() to convert it into a String. Change-Id: If661fc07cff542a57af3c28f27ab401ce7b3a656 Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
parent
4b706ff6cf
commit
d2593a24e6
|
@ -171,7 +171,7 @@ public class ProjectServlet extends GitServlet {
|
|||
}
|
||||
req.setAttribute(ATT_CONTROL, pc);
|
||||
|
||||
return manager.openRepository(pc.getProject().getName());
|
||||
return manager.openRepository(pc.getProject().getNameKey());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -323,9 +323,9 @@ class GitWebServlet extends HttpServlet {
|
|||
name = name.substring(0, name.length() - 4);
|
||||
}
|
||||
|
||||
final Project.NameKey nameKey = new Project.NameKey(name);
|
||||
final ProjectControl project;
|
||||
try {
|
||||
final Project.NameKey nameKey = new Project.NameKey(name);
|
||||
project = projectControl.validateFor(nameKey);
|
||||
if (!project.allRefsAreVisible()) {
|
||||
// Pretend the project doesn't exist
|
||||
|
@ -338,7 +338,7 @@ class GitWebServlet extends HttpServlet {
|
|||
|
||||
final Repository repo;
|
||||
try {
|
||||
repo = repoManager.openRepository(name);
|
||||
repo = repoManager.openRepository(nameKey);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
getServletContext().log("Cannot open repository", e);
|
||||
rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
|
|
|
@ -157,7 +157,7 @@ public class CatServlet extends HttpServlet {
|
|||
|
||||
final Repository repo;
|
||||
try {
|
||||
repo = repoManager.openRepository(project.getNameKey().get());
|
||||
repo = repoManager.openRepository(project.getNameKey());
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
getServletContext().log("Cannot open repository", e);
|
||||
rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
|
|
|
@ -77,7 +77,7 @@ class IncludedInDetailFactory extends Handler<IncludedInDetail> {
|
|||
final PatchSet patch =
|
||||
db.patchSets().get(control.getChange().currentPatchSetId());
|
||||
final Repository repo =
|
||||
repoManager.openRepository(control.getProject().getName());
|
||||
repoManager.openRepository(control.getProject().getNameKey());
|
||||
try {
|
||||
final RevWalk rw = new RevWalk(repo);
|
||||
try {
|
||||
|
|
|
@ -137,7 +137,7 @@ class PatchScriptFactory extends Handler<PatchScript> {
|
|||
|
||||
final Repository git;
|
||||
try {
|
||||
git = repoManager.openRepository(projectKey.get());
|
||||
git = repoManager.openRepository(projectKey);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
log.error("Repository " + projectKey + " not found", e);
|
||||
throw new NoSuchChangeException(changeId, e);
|
||||
|
|
|
@ -107,7 +107,7 @@ class AddBranch extends Handler<ListBranchesResult> {
|
|||
|
||||
final Branch.NameKey name = new Branch.NameKey(projectName, refname);
|
||||
final RefControl refControl = projectControl.controlForRef(name);
|
||||
final Repository repo = repoManager.openRepository(projectName.get());
|
||||
final Repository repo = repoManager.openRepository(projectName);
|
||||
try {
|
||||
final ObjectId revid = parseStartingRevision(repo);
|
||||
final RevWalk rw = verifyConnected(repo, revid);
|
||||
|
|
|
@ -73,7 +73,7 @@ class ChangeProjectSettings extends Handler<ProjectDetail> {
|
|||
projectCache.evict(proj);
|
||||
|
||||
if (!projectControl.getProjectState().isSpecialWildProject()) {
|
||||
repoManager.setProjectDescription(projectName.get(), update.getDescription());
|
||||
repoManager.setProjectDescription(projectName, update.getDescription());
|
||||
}
|
||||
|
||||
return projectDetailFactory.create(projectName).call();
|
||||
|
|
|
@ -88,7 +88,7 @@ class DeleteBranches extends Handler<Set<Branch.NameKey>> {
|
|||
}
|
||||
|
||||
final Set<Branch.NameKey> deleted = new HashSet<Branch.NameKey>();
|
||||
final Repository r = repoManager.openRepository(projectName.get());
|
||||
final Repository r = repoManager.openRepository(projectName);
|
||||
try {
|
||||
for (final Branch.NameKey branchKey : toRemove) {
|
||||
final String refname = branchKey.get();
|
||||
|
|
|
@ -70,7 +70,7 @@ class ListBranches extends Handler<ListBranchesResult> {
|
|||
|
||||
final Repository db;
|
||||
try {
|
||||
db = repoManager.openRepository(projectName.get());
|
||||
db = repoManager.openRepository(projectName);
|
||||
} catch (RepositoryNotFoundException noGitRepository) {
|
||||
return new ListBranchesResult(branches, false, true);
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ public class ListBranchesTest extends LocalDiskRepositoryTestCase {
|
|||
|
||||
validate().andReturn(pc);
|
||||
|
||||
expect(grm.openRepository(eq(name.get()))).andReturn(mockDb);
|
||||
expect(grm.openRepository(eq(name))).andReturn(mockDb);
|
||||
expect(mockDb.getAllRefs()).andDelegateTo(realDb);
|
||||
if (getHead) {
|
||||
expect(mockDb.getRef(HEAD)).andDelegateTo(realDb);
|
||||
|
@ -263,7 +263,7 @@ public class ListBranchesTest extends LocalDiskRepositoryTestCase {
|
|||
+ "master", null)));
|
||||
|
||||
validate().andReturn(pc);
|
||||
expect(grm.openRepository(eq(name.get()))).andReturn(mockDb);
|
||||
expect(grm.openRepository(eq(name))).andReturn(mockDb);
|
||||
expect(mockDb.getAllRefs()).andReturn(u);
|
||||
for (Ref ref : u.values()) {
|
||||
assumeVisible(ref, true);
|
||||
|
@ -291,7 +291,7 @@ public class ListBranchesTest extends LocalDiskRepositoryTestCase {
|
|||
u.put(HEAD, new SymbolicRef(HEAD, bar));
|
||||
|
||||
validate().andReturn(pc);
|
||||
expect(grm.openRepository(eq(name.get()))).andReturn(mockDb);
|
||||
expect(grm.openRepository(eq(name))).andReturn(mockDb);
|
||||
expect(mockDb.getAllRefs()).andReturn(u);
|
||||
assumeVisible(bar, false);
|
||||
assumeVisible(bar, false);
|
||||
|
@ -318,7 +318,7 @@ public class ListBranchesTest extends LocalDiskRepositoryTestCase {
|
|||
u.put(foo.getName(), foo);
|
||||
|
||||
validate().andReturn(pc);
|
||||
expect(grm.openRepository(eq(name.get()))).andReturn(mockDb);
|
||||
expect(grm.openRepository(eq(name))).andReturn(mockDb);
|
||||
expect(mockDb.getAllRefs()).andReturn(u);
|
||||
assumeVisible(bar, true);
|
||||
assumeVisible(bar, true);
|
||||
|
|
|
@ -116,7 +116,7 @@ public class ScanTrackingIds extends SiteProgram {
|
|||
final Project.NameKey project = change.getDest().getParentKey();
|
||||
final Repository git;
|
||||
try {
|
||||
git = gitManager.openRepository(project.get());
|
||||
git = gitManager.openRepository(project);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ public class ChangeHookRunner {
|
|||
*/
|
||||
private Repository openRepository(final Project.NameKey name) {
|
||||
try {
|
||||
return repoManager.openRepository(name.get());
|
||||
return repoManager.openRepository(name);
|
||||
} catch (RepositoryNotFoundException err) {
|
||||
log.warn("Cannot open repository " + name.get(), err);
|
||||
return null;
|
||||
|
|
|
@ -105,7 +105,7 @@ public class GitProjectImporter {
|
|||
final Project.NameKey nameKey = new Project.NameKey(name);
|
||||
final Project p = new Project(nameKey);
|
||||
|
||||
p.setDescription(repositoryManager.getProjectDescription(name));
|
||||
p.setDescription(repositoryManager.getProjectDescription(nameKey));
|
||||
p.setSubmitType(SubmitType.MERGE_IF_NECESSARY);
|
||||
p.setUseContributorAgreements(false);
|
||||
p.setUseSignedOffBy(false);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
package com.google.gerrit.server.git;
|
||||
|
||||
import com.google.gerrit.reviewdb.Project;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
|
@ -42,7 +43,7 @@ public interface GitRepositoryManager {
|
|||
* @throws RepositoryNotFoundException the name does not denote an existing
|
||||
* repository, or the name cannot be read as a repository.
|
||||
*/
|
||||
public abstract Repository openRepository(String name)
|
||||
public abstract Repository openRepository(Project.NameKey name)
|
||||
throws RepositoryNotFoundException;
|
||||
|
||||
/**
|
||||
|
@ -54,7 +55,7 @@ public interface GitRepositoryManager {
|
|||
* @throws RepositoryNotFoundException the name does not denote an existing
|
||||
* repository, or the name cannot be read as a repository.
|
||||
*/
|
||||
public abstract Repository createRepository(String name)
|
||||
public abstract Repository createRepository(Project.NameKey name)
|
||||
throws RepositoryNotFoundException;
|
||||
|
||||
/**
|
||||
|
@ -69,7 +70,7 @@ public interface GitRepositoryManager {
|
|||
* @throws IOException the description file exists, but is not readable by
|
||||
* this process.
|
||||
*/
|
||||
public abstract String getProjectDescription(final String name)
|
||||
public abstract String getProjectDescription(Project.NameKey name)
|
||||
throws RepositoryNotFoundException, IOException;
|
||||
|
||||
/**
|
||||
|
@ -81,6 +82,6 @@ public interface GitRepositoryManager {
|
|||
* @param name the repository name, relative to the base directory.
|
||||
* @param description new description text for the repository.
|
||||
*/
|
||||
public abstract void setProjectDescription(final String name,
|
||||
public abstract void setProjectDescription(Project.NameKey name,
|
||||
final String description);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package com.google.gerrit.server.git;
|
||||
|
||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||
import com.google.gerrit.reviewdb.Project;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.inject.Inject;
|
||||
|
@ -84,14 +85,18 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
|
|||
return basePath;
|
||||
}
|
||||
|
||||
public Repository openRepository(String name)
|
||||
private File gitDirOf(Project.NameKey name) {
|
||||
return new File(getBasePath(), name.get());
|
||||
}
|
||||
|
||||
public Repository openRepository(Project.NameKey name)
|
||||
throws RepositoryNotFoundException {
|
||||
if (isUnreasonableName(name)) {
|
||||
throw new RepositoryNotFoundException("Invalid name: " + name);
|
||||
}
|
||||
|
||||
try {
|
||||
final FileKey loc = FileKey.lenient(new File(basePath, name), FS.DETECTED);
|
||||
final FileKey loc = FileKey.lenient(gitDirOf(name), FS.DETECTED);
|
||||
return RepositoryCache.open(loc);
|
||||
} catch (IOException e1) {
|
||||
final RepositoryNotFoundException e2;
|
||||
|
@ -101,14 +106,14 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
|
|||
}
|
||||
}
|
||||
|
||||
public Repository createRepository(String name)
|
||||
public Repository createRepository(final Project.NameKey name)
|
||||
throws RepositoryNotFoundException {
|
||||
if (isUnreasonableName(name)) {
|
||||
throw new RepositoryNotFoundException("Invalid name: " + name);
|
||||
}
|
||||
|
||||
try {
|
||||
File dir = FileKey.resolve(new File(basePath, name), FS.DETECTED);
|
||||
File dir = FileKey.resolve(gitDirOf(name), FS.DETECTED);
|
||||
FileKey loc;
|
||||
if (dir != null) {
|
||||
// Already exists on disk, use the repository we found.
|
||||
|
@ -118,10 +123,11 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
|
|||
// It doesn't exist under any of the standard permutations
|
||||
// of the repository name, so prefer the standard bare name.
|
||||
//
|
||||
if (!name.endsWith(".git")) {
|
||||
name = name + ".git";
|
||||
String n = name.get();
|
||||
if (!n.endsWith(Constants.DOT_GIT_EXT)) {
|
||||
n = n + Constants.DOT_GIT_EXT;
|
||||
}
|
||||
loc = FileKey.exact(new File(basePath, name), FS.DETECTED);
|
||||
loc = FileKey.exact(new File(basePath, n), FS.DETECTED);
|
||||
}
|
||||
return RepositoryCache.open(loc, false);
|
||||
} catch (IOException e1) {
|
||||
|
@ -132,7 +138,7 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
|
|||
}
|
||||
}
|
||||
|
||||
public String getProjectDescription(final String name)
|
||||
public String getProjectDescription(final Project.NameKey name)
|
||||
throws RepositoryNotFoundException, IOException {
|
||||
final Repository e = openRepository(name);
|
||||
try {
|
||||
|
@ -160,7 +166,8 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void setProjectDescription(final String name, final String description) {
|
||||
public void setProjectDescription(final Project.NameKey name,
|
||||
final String description) {
|
||||
// Update git's description file, in case gitweb is being used
|
||||
//
|
||||
try {
|
||||
|
@ -193,7 +200,9 @@ public class LocalDiskRepositoryManager implements GitRepositoryManager {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isUnreasonableName(final String name) {
|
||||
private boolean isUnreasonableName(final Project.NameKey nameKey) {
|
||||
final String name = nameKey.get();
|
||||
|
||||
if (name.length() == 0) return true; // no empty paths
|
||||
|
||||
if (name.indexOf('\\') >= 0) return true; // no windows/dos stlye paths
|
||||
|
|
|
@ -240,11 +240,11 @@ public class MergeOp {
|
|||
}
|
||||
|
||||
private void openRepository() throws MergeException {
|
||||
final String name = destBranch.getParentKey().get();
|
||||
final Project.NameKey name = destBranch.getParentKey();
|
||||
try {
|
||||
db = repoManager.openRepository(name);
|
||||
} catch (RepositoryNotFoundException notGit) {
|
||||
final String m = "Repository \"" + name + "\" unknown.";
|
||||
final String m = "Repository \"" + name.get() + "\" unknown.";
|
||||
throw new MergeException(m, notGit);
|
||||
}
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ class PushOp implements ProjectRunnable {
|
|||
// since the canceled flag would be set locking the queue.
|
||||
if (!canceled) {
|
||||
try {
|
||||
db = repoManager.openRepository(projectName.get());
|
||||
db = repoManager.openRepository(projectName);
|
||||
runImpl();
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
log.error("Cannot replicate " + projectName + "; " + e.getMessage());
|
||||
|
|
|
@ -48,12 +48,11 @@ import java.util.TreeSet;
|
|||
/** Sends an email to one or more interested parties. */
|
||||
public abstract class ChangeEmail extends OutgoingEmail {
|
||||
protected final Change change;
|
||||
protected String projectName;
|
||||
protected PatchSet patchSet;
|
||||
protected PatchSetInfo patchSetInfo;
|
||||
protected ChangeMessage changeMessage;
|
||||
|
||||
private ProjectState projectState;
|
||||
protected ProjectState projectState;
|
||||
protected ChangeData changeData;
|
||||
|
||||
protected ChangeEmail(EmailArguments ea, final Change c, final String mc) {
|
||||
|
@ -105,11 +104,8 @@ public abstract class ChangeEmail extends OutgoingEmail {
|
|||
protected void init() throws EmailException {
|
||||
if (args.projectCache != null) {
|
||||
projectState = args.projectCache.get(change.getProject());
|
||||
projectName =
|
||||
projectState != null ? projectState.getProject().getName() : null;
|
||||
} else {
|
||||
projectState = null;
|
||||
projectName = null;
|
||||
}
|
||||
|
||||
if (patchSet == null) {
|
||||
|
@ -399,7 +395,8 @@ public abstract class ChangeEmail extends OutgoingEmail {
|
|||
velocityContext.put("coverLetter", getCoverLetter());
|
||||
velocityContext.put("branch", change.getDest());
|
||||
velocityContext.put("fromName", getNameFor(fromId));
|
||||
velocityContext.put("projectName", projectName);
|
||||
velocityContext.put("projectName", //
|
||||
projectState != null ? projectState.getProject().getName() : null);
|
||||
velocityContext.put("patchSet", patchSet);
|
||||
velocityContext.put("patchSetInfo", patchSetInfo);
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ public class CommentSender extends ReplyToChangeSender {
|
|||
|
||||
private Repository getRepository() {
|
||||
try {
|
||||
return args.server.openRepository(projectName);
|
||||
return args.server.openRepository(projectState.getProject().getNameKey());
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ class PatchListLoader extends EntryCreator<PatchListKey, PatchList> {
|
|||
|
||||
@Override
|
||||
public PatchList createEntry(final PatchListKey key) throws Exception {
|
||||
final Repository repo = repoManager.openRepository(key.projectKey.get());
|
||||
final Repository repo = repoManager.openRepository(key.projectKey);
|
||||
try {
|
||||
return readPatchList(key, repo);
|
||||
} finally {
|
||||
|
|
|
@ -76,8 +76,7 @@ public class PatchSetInfoFactory {
|
|||
final PatchSet patchSet = db.patchSets().get(patchSetId);
|
||||
final Change change = db.changes().get(patchSet.getId().getParentKey());
|
||||
final Project.NameKey projectKey = change.getProject();
|
||||
final String projectName = projectKey.get();
|
||||
repo = repoManager.openRepository(projectName);
|
||||
repo = repoManager.openRepository(projectKey);
|
||||
final RevWalk rw = new RevWalk(repo);
|
||||
try {
|
||||
final RevCommit src =
|
||||
|
|
|
@ -92,7 +92,7 @@ public class MessagePredicate extends OperatorPredicate<ChangeData> {
|
|||
}
|
||||
|
||||
try {
|
||||
final Repository repo = repoManager.openRepository(projectName.get());
|
||||
final Repository repo = repoManager.openRepository(projectName);
|
||||
try {
|
||||
final RevWalk rw = new RevWalk(repo);
|
||||
try {
|
||||
|
|
|
@ -93,11 +93,10 @@ public abstract class AbstractGitCommand extends BaseCommand {
|
|||
private void service() throws IOException, Failure {
|
||||
project = projectControl.getProjectState().getProject();
|
||||
|
||||
final String name = project.getName();
|
||||
try {
|
||||
repo = repoManager.openRepository(name);
|
||||
repo = repoManager.openRepository(project.getNameKey());
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
throw new Failure(1, "fatal: '" + name + "': not a git archive", e);
|
||||
throw new Failure(1, "fatal: '" + project.getName() + "': not a git archive", e);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -119,6 +119,8 @@ final class CreateProject extends BaseCommand {
|
|||
@GerritPersonIdent
|
||||
private PersonIdent serverIdent;
|
||||
|
||||
private Project.NameKey nameKey;
|
||||
|
||||
@Override
|
||||
public void start(final Environment env) {
|
||||
startThread(new CommandRunnable() {
|
||||
|
@ -130,9 +132,10 @@ final class CreateProject extends BaseCommand {
|
|||
|
||||
try {
|
||||
validateParameters();
|
||||
nameKey = new Project.NameKey(projectName);
|
||||
|
||||
if (!permissionsOnly) {
|
||||
final Repository repo = repoManager.createRepository(projectName);
|
||||
final Repository repo = repoManager.createRepository(nameKey);
|
||||
try {
|
||||
repo.create(true);
|
||||
|
||||
|
@ -140,14 +143,12 @@ final class CreateProject extends BaseCommand {
|
|||
u.disableRefLog();
|
||||
u.link(branch);
|
||||
|
||||
repoManager
|
||||
.setProjectDescription(projectName, projectDescription);
|
||||
repoManager.setProjectDescription(nameKey, projectDescription);
|
||||
|
||||
final Project.NameKey project = new Project.NameKey(projectName);
|
||||
rq.replicateNewProject(project, branch);
|
||||
rq.replicateNewProject(nameKey, branch);
|
||||
|
||||
if (createEmptyCommit) {
|
||||
createEmptyCommit(repo, project, branch);
|
||||
createEmptyCommit(repo, nameKey, branch);
|
||||
}
|
||||
} finally {
|
||||
repo.close();
|
||||
|
@ -198,12 +199,10 @@ final class CreateProject extends BaseCommand {
|
|||
}
|
||||
|
||||
private void createProject() throws OrmException {
|
||||
final Project.NameKey newProjectNameKey = new Project.NameKey(projectName);
|
||||
|
||||
List<RefRight> access = new ArrayList<RefRight>();
|
||||
for (AccountGroup.Id ownerId : ownerIds) {
|
||||
final RefRight.Key prk =
|
||||
new RefRight.Key(newProjectNameKey, new RefRight.RefPattern(
|
||||
new RefRight.Key(nameKey, new RefRight.RefPattern(
|
||||
RefRight.ALL), ApprovalCategory.OWN, ownerId);
|
||||
final RefRight pr = new RefRight(prk);
|
||||
pr.setMaxValue((short) 1);
|
||||
|
@ -212,7 +211,7 @@ final class CreateProject extends BaseCommand {
|
|||
}
|
||||
db.refRights().insert(access);
|
||||
|
||||
final Project newProject = new Project(newProjectNameKey);
|
||||
final Project newProject = new Project(nameKey);
|
||||
newProject.setDescription(projectDescription);
|
||||
newProject.setSubmitType(submitType);
|
||||
newProject.setUseContributorAgreements(contributorAgreements);
|
||||
|
@ -227,9 +226,9 @@ final class CreateProject extends BaseCommand {
|
|||
}
|
||||
|
||||
private void validateParameters() throws Failure {
|
||||
if (projectName.endsWith(".git")) {
|
||||
projectName =
|
||||
projectName.substring(0, projectName.length() - ".git".length());
|
||||
if (projectName.endsWith(Constants.DOT_GIT_EXT)) {
|
||||
projectName = projectName.substring(0, //
|
||||
projectName.length() - Constants.DOT_GIT_EXT.length());
|
||||
}
|
||||
|
||||
if (!CollectionsUtil.isAnyIncludedIn(currentUser.getEffectiveGroups(), projectCreatorGroups)) {
|
||||
|
|
|
@ -170,7 +170,7 @@ final class ListProjects extends BaseCommand {
|
|||
|
||||
private Ref getBranchRef(Project.NameKey projectName) {
|
||||
try {
|
||||
final Repository r = repoManager.openRepository(projectName.get());
|
||||
final Repository r = repoManager.openRepository(projectName);
|
||||
try {
|
||||
return r.getRef(showBranch);
|
||||
} finally {
|
||||
|
|
Loading…
Reference in New Issue