Skip to content

Commit

Permalink
Fix to show project creators correctly (line#909)
Browse files Browse the repository at this point in the history
Motivation:
The current creator of a project is the creator of the internal `dogma` repository, consistently set as `System`. We should show the correct creator which is stored in the `metadata.json` file.

A noteworthy observation is that only the email of the creator is stored in `metadata.json` instead of the complete `Author` information. A temporary solution involves restoring the `Author` using the email, with plans to revisit this approach if issues arise.

Modifications:
- Fix to show project creators correctly using information stored in the `metadata.json` file.

Result:
- Close line#908 
- The project creator is now correctly retrieved based on the information stored in the `metadata.json` file.
  • Loading branch information
minwoox authored Feb 1, 2024
1 parent 9510c7b commit e871425
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
@State(Scope.Benchmark)
public class GitRepositoryBenchmark {

private static final Author AUTHOR = new Author("[email protected]");
private static final Author AUTHOR = Author.ofEmail("[email protected]");

@Param({ "0", "2000", "4000", "6000", "8000" })
private int previousCommits;
Expand Down
12 changes: 12 additions & 0 deletions common/src/main/java/com/linecorp/centraldogma/common/Author.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.linecorp.centraldogma.common;

import static com.linecorp.centraldogma.internal.Util.emailToUsername;
import static java.util.Objects.requireNonNull;

import com.fasterxml.jackson.annotation.JsonCreator;
Expand Down Expand Up @@ -43,12 +44,23 @@ public class Author {
*/
public static final Author UNKNOWN = new Author("Unknown", "[email protected]");

/**
* Create a new {@link Author} with the {@code email}.
* The {@link #name()} will be set to the username of the {@code email}.
*/
public static Author ofEmail(String email) {
return new Author(emailToUsername(email, "email"), email);
}

private final String name;
private final String email;

/**
* Creates a new instance with the specified e-mail address.
*
* @deprecated Use {@link #ofEmail(String)}.
*/
@Deprecated
public Author(String email) {
this(email, email);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ void testJsonConversion() {
" \"email\": \"[email protected]\"" +
'}');

TestUtil.assertJsonConversion(new Author("[email protected]"),
TestUtil.assertJsonConversion(Author.ofEmail("[email protected]"),
'{' +
" \"name\": \"bart@simpsonsworld.com\"," +
" \"name\": \"bart\"," +
" \"email\": \"[email protected]\"" +
'}');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,19 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.ImmutableMap;

import com.linecorp.centraldogma.common.Author;
import com.linecorp.centraldogma.common.CentralDogmaException;
import com.linecorp.centraldogma.common.Change;
import com.linecorp.centraldogma.common.Entry;
import com.linecorp.centraldogma.common.Markup;
import com.linecorp.centraldogma.common.ProjectExistsException;
import com.linecorp.centraldogma.common.ProjectNotFoundException;
import com.linecorp.centraldogma.common.Query;
import com.linecorp.centraldogma.common.RepositoryExistsException;
import com.linecorp.centraldogma.common.Revision;
import com.linecorp.centraldogma.internal.Jackson;
Expand All @@ -61,6 +66,8 @@ public class DefaultProject implements Project {
private static final Logger logger = LoggerFactory.getLogger(DefaultProject.class);

private final String name;
private final long creationTimeMillis;
private final Author author;
final RepositoryManager repos;
private final AtomicReference<MetaRepository> metaRepo = new AtomicReference<>();

Expand All @@ -82,6 +89,14 @@ public class DefaultProject implements Project {
boolean success = false;
try {
createReservedRepos(System.currentTimeMillis());
final UserAndTimestamp creation = metadataCreation();
if (creation != null) {
creationTimeMillis = creation.timestampMillis();
author = Author.ofEmail(creation.user());
} else {
creationTimeMillis = repos.get(REPO_DOGMA).creationTimeMillis();
author = repos.get(REPO_DOGMA).author();
}
success = true;
} finally {
if (!success) {
Expand Down Expand Up @@ -109,6 +124,8 @@ public class DefaultProject implements Project {
try {
createReservedRepos(creationTimeMillis);
initializeMetadata(creationTimeMillis, author);
this.creationTimeMillis = creationTimeMillis;
this.author = author;
success = true;
} finally {
if (!success) {
Expand All @@ -117,6 +134,23 @@ public class DefaultProject implements Project {
}
}

@Nullable
private UserAndTimestamp metadataCreation() {
if (name.equals(INTERNAL_PROJECT_DOGMA)) {
return null;
}
final Entry<JsonNode> metadata = repos.get(REPO_DOGMA)
.get(Revision.HEAD, Query.ofJson(METADATA_JSON))
.join();
try {
return Jackson.treeToValue(metadata.content(), ProjectMetadata.class)
.creation();
} catch (JsonParseException | JsonMappingException e) {
logger.warn("Failed to retrieve creation in {} file. project: {}", METADATA_JSON, name);
return null;
}
}

private RepositoryManager newRepoManager(File rootDir, Executor repositoryWorker, Executor purgeWorker,
@Nullable RepositoryCache cache) {
// Enable caching if 'cache' is not null.
Expand Down Expand Up @@ -174,6 +208,16 @@ public String name() {
return name;
}

@Override
public long creationTimeMillis() {
return creationTimeMillis;
}

@Override
public Author author() {
return author;
}

@Override
public MetaRepository metaRepo() {
MetaRepository metaRepo = this.metaRepo.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ public String timestamp() {
return timestampAsText;
}

/**
* Returns the epoch milliseconds of the {@link #timestamp()}.
*/
public long timestampMillis() {
return timestamp.toEpochMilli();
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,12 @@ public interface Project {
/**
* Returns the creation time of this project, in milliseconds.
*/
default long creationTimeMillis() {
return repos().get(REPO_DOGMA).creationTimeMillis();
}
long creationTimeMillis();

/**
* Returns the author who initially created this project.
*/
default Author author() {
return repos().get(REPO_DOGMA).author();
}
Author author();

/**
* Returns the {@link MetaRepository} of this project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ void unremoveProject() {
'{' +
" \"name\": \"bar\"," +
" \"creator\": {" +
" \"name\": \"System\"," +
" \"email\": \"system@localhost.localdomain\"" +
" \"name\": \"admin\"," +
" \"email\": \"admin@localhost.localdomain\"" +
" }," +
" \"url\": \"/api/v1/projects/bar\"," +
" \"createdAt\": \"${json-unit.ignore}\"" +
Expand Down Expand Up @@ -187,26 +187,26 @@ void listProjects() {
" {" +
" \"name\": \"hyangtack\"," +
" \"creator\": {" +
" \"name\": \"System\"," +
" \"email\": \"system@localhost.localdomain\"" +
" \"name\": \"admin\"," +
" \"email\": \"admin@localhost.localdomain\"" +
" }," +
" \"url\": \"/api/v1/projects/hyangtack\"," +
" \"createdAt\": \"${json-unit.ignore}\"" +
" }," +
" {" +
" \"name\": \"minwoox\"," +
" \"creator\": {" +
" \"name\": \"System\"," +
" \"email\": \"system@localhost.localdomain\"" +
" \"name\": \"admin\"," +
" \"email\": \"admin@localhost.localdomain\"" +
" }," +
" \"url\": \"/api/v1/projects/minwoox\"," +
" \"createdAt\": \"${json-unit.ignore}\"" +
" }," +
" {" +
" \"name\": \"trustin\"," +
" \"creator\": {" +
" \"name\": \"System\"," +
" \"email\": \"system@localhost.localdomain\"" +
" \"name\": \"admin\"," +
" \"email\": \"admin@localhost.localdomain\"" +
" }," +
" \"url\": \"/api/v1/projects/trustin\"," +
" \"createdAt\": \"${json-unit.ignore}\"" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ class TokenServiceTest {
@RegisterExtension
static final ProjectManagerExtension manager = new ProjectManagerExtension();

private static final Author adminAuthor = new Author("[email protected]");
private static final Author guestAuthor = new Author("[email protected]");
private static final Author adminAuthor = Author.ofEmail("[email protected]");
private static final Author guestAuthor = Author.ofEmail("[email protected]");
private static final User admin = new User("[email protected]", User.LEVEL_ADMIN);
private static final User guest = new User("[email protected]");
private static final JsonNode activation = Jackson.valueToTree(
Expand Down

0 comments on commit e871425

Please sign in to comment.