mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-06 21:45:50 +01:00
(refs #31)Make it possible to create empty repository.
This commit is contained in:
@@ -20,11 +20,13 @@ trait CreateRepositoryControllerBase extends ControllerBase {
|
|||||||
self: RepositoryService with WikiService with LabelsService with ActivityService
|
self: RepositoryService with WikiService with LabelsService with ActivityService
|
||||||
with UsersAuthenticator =>
|
with UsersAuthenticator =>
|
||||||
|
|
||||||
case class RepositoryCreationForm(name: String, description: Option[String])
|
case class RepositoryCreationForm(name: String, description: Option[String], isPrivate: Boolean, createReadme: Boolean)
|
||||||
|
|
||||||
val form = mapping(
|
val form = mapping(
|
||||||
"name" -> trim(label("Repository name", text(required, maxlength(40), identifier, unique))),
|
"name" -> trim(label("Repository name", text(required, maxlength(40), identifier, unique))),
|
||||||
"description" -> trim(label("Description" , optional(text())))
|
"description" -> trim(label("Description" , optional(text()))),
|
||||||
|
"isPrivate" -> trim(label("Repository Type", boolean())),
|
||||||
|
"createReadme" -> trim(label("Create README" , boolean()))
|
||||||
)(RepositoryCreationForm.apply)
|
)(RepositoryCreationForm.apply)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +44,7 @@ trait CreateRepositoryControllerBase extends ControllerBase {
|
|||||||
val loginUserName = loginAccount.userName
|
val loginUserName = loginAccount.userName
|
||||||
|
|
||||||
// Insert to the database at first
|
// Insert to the database at first
|
||||||
createRepository(form.name, loginUserName, form.description)
|
createRepository(form.name, loginUserName, form.description, form.isPrivate)
|
||||||
|
|
||||||
// Insert default labels
|
// Insert default labels
|
||||||
createLabel(loginUserName, form.name, "bug", "fc2929")
|
createLabel(loginUserName, form.name, "bug", "fc2929")
|
||||||
@@ -62,26 +64,28 @@ trait CreateRepositoryControllerBase extends ControllerBase {
|
|||||||
config.setBoolean("http", null, "receivepack", true)
|
config.setBoolean("http", null, "receivepack", true)
|
||||||
config.save
|
config.save
|
||||||
|
|
||||||
val tmpdir = getInitRepositoryDir(loginUserName, form.name)
|
if(form.createReadme){
|
||||||
try {
|
val tmpdir = getInitRepositoryDir(loginUserName, form.name)
|
||||||
// Clone the repository
|
try {
|
||||||
Git.cloneRepository.setURI(gitdir.toURI.toString).setDirectory(tmpdir).call
|
// Clone the repository
|
||||||
|
Git.cloneRepository.setURI(gitdir.toURI.toString).setDirectory(tmpdir).call
|
||||||
|
|
||||||
// Create README.md
|
// Create README.md
|
||||||
FileUtils.writeStringToFile(new File(tmpdir, "README.md"),
|
FileUtils.writeStringToFile(new File(tmpdir, "README.md"),
|
||||||
if(form.description.nonEmpty){
|
if(form.description.nonEmpty){
|
||||||
form.name + "\n===============\n\n" + form.description.get
|
form.name + "\n===============\n\n" + form.description.get
|
||||||
} else {
|
} else {
|
||||||
form.name + "\n===============\n"
|
form.name + "\n===============\n"
|
||||||
}, "UTF-8")
|
}, "UTF-8")
|
||||||
|
|
||||||
val git = Git.open(tmpdir)
|
val git = Git.open(tmpdir)
|
||||||
git.add.addFilepattern("README.md").call
|
git.add.addFilepattern("README.md").call
|
||||||
git.commit.setMessage("Initial commit").call
|
git.commit.setMessage("Initial commit").call
|
||||||
git.push.call
|
git.push.call
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
FileUtils.deleteDirectory(tmpdir)
|
FileUtils.deleteDirectory(tmpdir)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Wiki repository
|
// Create Wiki repository
|
||||||
|
|||||||
@@ -210,37 +210,36 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
* @return HTML of the file list
|
* @return HTML of the file list
|
||||||
*/
|
*/
|
||||||
private def fileList(repository: RepositoryService.RepositoryInfo, revstr: String = "", path: String = ".") = {
|
private def fileList(repository: RepositoryService.RepositoryInfo, revstr: String = "", path: String = ".") = {
|
||||||
val revision = if(revstr.isEmpty){
|
if(repository.commitCount == 0){
|
||||||
repository.repository.defaultBranch
|
repo.html.guide(repository)
|
||||||
} else {
|
} else {
|
||||||
revstr
|
val revision = if(revstr.isEmpty) repository.repository.defaultBranch else revstr
|
||||||
}
|
|
||||||
|
|
||||||
JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git =>
|
JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git =>
|
||||||
// get latest commit
|
// get latest commit
|
||||||
val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(revision))
|
val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(revision))
|
||||||
|
// get files
|
||||||
|
val files = JGitUtil.getFileList(git, revision, path)
|
||||||
|
// process README.md
|
||||||
|
val readme = files.find(_.name == "README.md").map { file =>
|
||||||
|
new String(JGitUtil.getContent(Git.open(getRepositoryDir(repository.owner, repository.name)), file.id, true).get, "UTF-8")
|
||||||
|
}
|
||||||
|
|
||||||
val files = JGitUtil.getFileList(git, revision, path)
|
repo.html.files(
|
||||||
|
// current branch
|
||||||
// process README.md
|
revision,
|
||||||
val readme = files.find(_.name == "README.md").map { file =>
|
// repository
|
||||||
new String(JGitUtil.getContent(Git.open(getRepositoryDir(repository.owner, repository.name)), file.id, true).get, "UTF-8")
|
repository,
|
||||||
|
// current path
|
||||||
|
if(path == ".") Nil else path.split("/").toList,
|
||||||
|
// latest commit
|
||||||
|
new JGitUtil.CommitInfo(revCommit),
|
||||||
|
// file list
|
||||||
|
files,
|
||||||
|
// readme
|
||||||
|
readme
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.html.files(
|
|
||||||
// current branch
|
|
||||||
revision,
|
|
||||||
// repository
|
|
||||||
repository,
|
|
||||||
// current path
|
|
||||||
if(path == ".") Nil else path.split("/").toList,
|
|
||||||
// latest commit
|
|
||||||
new JGitUtil.CommitInfo(revCommit),
|
|
||||||
// file list
|
|
||||||
files,
|
|
||||||
// readme
|
|
||||||
readme
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,19 +11,17 @@ trait RepositoryService { self: AccountService =>
|
|||||||
/**
|
/**
|
||||||
* Creates a new repository.
|
* Creates a new repository.
|
||||||
*
|
*
|
||||||
* The project is created as public repository at first. Users can modify the project type at the repository settings
|
|
||||||
* page after the project creation to configure the project as the private repository.
|
|
||||||
*
|
|
||||||
* @param repositoryName the repository name
|
* @param repositoryName the repository name
|
||||||
* @param userName the user name of the repository owner
|
* @param userName the user name of the repository owner
|
||||||
* @param description the repository description
|
* @param description the repository description
|
||||||
|
* @param isPrivate the repository type (private is true, otherwise false)
|
||||||
*/
|
*/
|
||||||
def createRepository(repositoryName: String, userName: String, description: Option[String]): Unit = {
|
def createRepository(repositoryName: String, userName: String, description: Option[String], isPrivate: Boolean): Unit = {
|
||||||
Repositories insert
|
Repositories insert
|
||||||
Repository(
|
Repository(
|
||||||
userName = userName,
|
userName = userName,
|
||||||
repositoryName = repositoryName,
|
repositoryName = repositoryName,
|
||||||
isPrivate = false,
|
isPrivate = isPrivate,
|
||||||
description = description,
|
description = description,
|
||||||
defaultBranch = "master",
|
defaultBranch = "master",
|
||||||
registeredDate = currentDate,
|
registeredDate = currentDate,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.eclipse.jgit.diff.DiffEntry.ChangeType
|
|||||||
import org.eclipse.jgit.util.io.DisabledOutputStream
|
import org.eclipse.jgit.util.io.DisabledOutputStream
|
||||||
import org.eclipse.jgit.errors.MissingObjectException
|
import org.eclipse.jgit.errors.MissingObjectException
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import org.eclipse.jgit.api.errors.NoHeadException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides complex JGit operations.
|
* Provides complex JGit operations.
|
||||||
@@ -142,28 +143,35 @@ object JGitUtil {
|
|||||||
*/
|
*/
|
||||||
def getRepositoryInfo(owner: String, repository: String, baseUrl: String): RepositoryInfo = {
|
def getRepositoryInfo(owner: String, repository: String, baseUrl: String): RepositoryInfo = {
|
||||||
withGit(getRepositoryDir(owner, repository)){ git =>
|
withGit(getRepositoryDir(owner, repository)){ git =>
|
||||||
// get commit count
|
try {
|
||||||
val i = git.log.all.call.iterator
|
// get commit count
|
||||||
var commitCount = 0
|
val i = git.log.all.call.iterator
|
||||||
while(i.hasNext && commitCount <= 1000){
|
var commitCount = 0
|
||||||
i.next
|
while(i.hasNext && commitCount <= 1000){
|
||||||
commitCount = commitCount + 1
|
i.next
|
||||||
}
|
commitCount = commitCount + 1
|
||||||
|
}
|
||||||
|
|
||||||
RepositoryInfo(
|
RepositoryInfo(
|
||||||
owner, repository, baseUrl + "/git/%s/%s.git".format(owner, repository),
|
owner, repository, baseUrl + "/git/%s/%s.git".format(owner, repository),
|
||||||
// commit count
|
// commit count
|
||||||
commitCount,
|
commitCount,
|
||||||
// branches
|
// branches
|
||||||
git.branchList.call.asScala.map { ref =>
|
git.branchList.call.asScala.map { ref =>
|
||||||
ref.getName.replaceFirst("^refs/heads/", "")
|
ref.getName.replaceFirst("^refs/heads/", "")
|
||||||
}.toList,
|
}.toList,
|
||||||
// tags
|
// tags
|
||||||
git.tagList.call.asScala.map { ref =>
|
git.tagList.call.asScala.map { ref =>
|
||||||
val revCommit = getRevCommitFromId(git, ref.getObjectId)
|
val revCommit = getRevCommitFromId(git, ref.getObjectId)
|
||||||
TagInfo(ref.getName.replaceFirst("^refs/tags/", ""), revCommit.getCommitterIdent.getWhen, revCommit.getName)
|
TagInfo(ref.getName.replaceFirst("^refs/tags/", ""), revCommit.getCommitterIdent.getWhen, revCommit.getName)
|
||||||
}.toList
|
}.toList
|
||||||
)
|
)
|
||||||
|
} catch {
|
||||||
|
// not initialized
|
||||||
|
case e: NoHeadException => RepositoryInfo(
|
||||||
|
owner, repository, baseUrl + "/git/%s/%s.git".format(owner, repository), 0, Nil, Nil)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@()(implicit context: app.Context)
|
@()(implicit context: app.Context)
|
||||||
@import context._
|
@import context._
|
||||||
@main("Create a New Repository"){
|
@main("Create a New Repository"){
|
||||||
|
<div style="width: 600px; margin: 10px auto;">
|
||||||
<form id="form" method="post" action="@path/new" validate="true">
|
<form id="form" method="post" action="@path/new" validate="true">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="name"><strong>Repository name</strong></label>
|
<label for="name"><strong>Repository name</strong></label>
|
||||||
@@ -9,10 +10,38 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label for="description"><strong>Description</strong> (optional)</label>
|
<label for="description"><strong>Description</strong> (optional)</label>
|
||||||
<input type="text" name="description" id="description" style="width: 600px;"/>
|
<input type="text" name="description" id="description" style="width: 95%;"/>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="margin">
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="isPrivate" value="false" checked>
|
||||||
|
<strong>Public</strong><br>
|
||||||
|
<div>
|
||||||
|
<span class="note">All users and guests can read this repository.</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="isPrivate" value="true">
|
||||||
|
<strong>Private</strong><br>
|
||||||
|
<div>
|
||||||
|
<span class="note">Only collaborators can read this repository.</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="margin">
|
||||||
|
<label for="createReadme">
|
||||||
|
<input type="checkbox" name="createReadme" id="createReadme"/>
|
||||||
|
<strong>Initialize this repository with a README</strong>
|
||||||
|
<div>
|
||||||
|
<span class="note">This will allow you to <code>git clone</code> the repository immediately.</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="margin">
|
||||||
<input type="submit" class="btn btn-success" value="Create repository"/>
|
<input type="submit" class="btn btn-success" value="Create repository"/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
21
src/main/twirl/repo/guide.scala.html
Normal file
21
src/main/twirl/repo/guide.scala.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
@(repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context)
|
||||||
|
@import context._
|
||||||
|
@import view.helpers._
|
||||||
|
@html.main(repository.owner + "/" + repository.name) {
|
||||||
|
@html.header("code", repository)
|
||||||
|
<h3 style="margin-top: 30px;">Create a new repository on the command line</h3>
|
||||||
|
<pre>
|
||||||
|
touch README.md
|
||||||
|
git init
|
||||||
|
git add README.md
|
||||||
|
git commit -m "first commit"
|
||||||
|
git remote add origin @repository.url
|
||||||
|
git push -u origin master
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h3 style="margin-top: 30px;">Push an existing repository from the command line</h3>
|
||||||
|
<pre>
|
||||||
|
git remote add origin @repository.url
|
||||||
|
git push -u origin master
|
||||||
|
</pre>
|
||||||
|
}
|
||||||
@@ -22,17 +22,24 @@
|
|||||||
</select>
|
</select>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<hr>
|
<hr>
|
||||||
<fieldset>
|
<fieldset class="margin">
|
||||||
<label><strong>Repository Type</strong></label>
|
<label>
|
||||||
<label>
|
<input type="radio" name="isPrivate" value="false" checked>
|
||||||
<input type="radio" name="isPrivate" value="false"@if(!repository.repository.isPrivate){ checked}>
|
<strong>Public</strong><br>
|
||||||
<strong>Public</strong> - All users and guests can read this repository.
|
<div>
|
||||||
</label>
|
<span class="note">All users and guests can read this repository.</span>
|
||||||
<label>
|
</div>
|
||||||
<input type="radio" name="isPrivate" value="true"@if(repository.repository.isPrivate){ checked}>
|
</label>
|
||||||
<strong>Private</strong> - Only collaborators can read this repository.
|
</fieldset>
|
||||||
</label>
|
<fieldset>
|
||||||
</fieldset>
|
<label>
|
||||||
|
<input type="radio" name="isPrivate" value="true">
|
||||||
|
<strong>Private</strong><br>
|
||||||
|
<div>
|
||||||
|
<span class="note">Only collaborators can read this repository.</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@*
|
@*
|
||||||
|
|||||||
@@ -193,6 +193,19 @@ hr {
|
|||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.note {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.margin {
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
margin-top: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Sign-in form */
|
||||||
|
/****************************************************************************/
|
||||||
div.signin-form {
|
div.signin-form {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
margin: 30px auto;
|
margin: 30px auto;
|
||||||
|
|||||||
Reference in New Issue
Block a user