All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.server.notedb.DraftCommentsNotesReader Maven / Gradle / Ivy

There is a newer version: 3.11.0-rc3
Show newest version
// Copyright (C) 2023 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.notedb;

import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.DraftCommentsReader;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.query.change.ChangeNumberVirtualIdAlgorithm;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

@Singleton
public class DraftCommentsNotesReader implements DraftCommentsReader {
  private final DraftCommentNotes.Factory draftCommentNotesFactory;
  private final GitRepositoryManager repoManager;
  private final AllUsersName allUsers;
  private final ChangeNumberVirtualIdAlgorithm virtualIdAlgorithm;

  @Inject
  DraftCommentsNotesReader(
      DraftCommentNotes.Factory draftCommentNotesFactory,
      GitRepositoryManager repoManager,
      AllUsersName allUsers,
      ChangeNumberVirtualIdAlgorithm virtualIdAlgorithm) {
    this.draftCommentNotesFactory = draftCommentNotesFactory;
    this.repoManager = repoManager;
    this.allUsers = allUsers;
    this.virtualIdAlgorithm = virtualIdAlgorithm;
  }

  @Override
  public Optional getDraftComment(
      ChangeNotes notes, IdentifiedUser author, Comment.Key key) {
    return getDraftsByChangeAndDraftAuthor(notes, author.getAccountId()).stream()
        .filter(c -> key.equals(c.key))
        .findFirst();
  }

  @Override
  public List getDraftsByChangeAndDraftAuthor(ChangeNotes notes, Account.Id author) {
    return sort(new ArrayList<>(notes.getDraftComments(author, getVirtualId(notes))));
  }

  @Override
  public List getDraftsByChangeAndDraftAuthor(Change.Id changeId, Account.Id author) {
    return sort(
        new ArrayList<>(draftCommentNotesFactory.create(changeId, author).load().getComments()));
  }

  @Override
  public List getDraftsByPatchSetAndDraftAuthor(
      ChangeNotes notes, PatchSet.Id psId, Account.Id author) {
    return sort(
        notes.load().getDraftComments(author, getVirtualId(notes)).stream()
            .filter(c -> c.key.patchSetId == psId.get())
            .collect(Collectors.toList()));
  }

  @Override
  public List getDraftsByChangeForAllAuthors(ChangeNotes notes) {
    List comments = new ArrayList<>();
    for (Ref ref : getDraftRefs(notes)) {
      Account.Id account = Account.Id.fromRefSuffix(ref.getName());
      if (account != null) {
        comments.addAll(getDraftsByChangeAndDraftAuthor(notes, account));
      }
    }
    return sort(comments);
  }

  @Override
  public Set getUsersWithDrafts(ChangeNotes changeNotes) {
    Set res = new HashSet<>();
    for (Ref ref : getDraftRefs(changeNotes)) {
      Account.Id account = Account.Id.fromRefSuffix(ref.getName());
      if (account != null
          // Double-check that any drafts exist for this user after
          // filtering out zombies. If some but not all drafts in the ref
          // were zombies, the returned Ref still includes those zombies;
          // this is suboptimal, but is ok for the purposes of
          // draftsByUser(), and easier than trying to rebuild the change at
          // this point.
          && !changeNotes.getDraftComments(account, ref).isEmpty()) {
        res.add(account);
      }
    }
    return res;
  }

  @Override
  public Set getChangesWithDrafts(Account.Id author) {
    Set changes = new HashSet<>();
    try (Repository repo = repoManager.openRepository(allUsers)) {
      for (Ref ref : repo.getRefDatabase().getRefsByPrefix(RefNames.REFS_DRAFT_COMMENTS)) {
        Integer accountIdFromRef = RefNames.parseRefSuffix(ref.getName());
        if (accountIdFromRef != null && accountIdFromRef == author.get()) {
          Change.Id changeId = Change.Id.fromAllUsersRef(ref.getName());
          if (changeId == null) {
            continue;
          }
          changes.add(changeId);
        }
      }
    } catch (IOException e) {
      throw new StorageException(e);
    }
    return changes;
  }

  private List getDraftRefs(ChangeNotes notes) {
    try (Repository repo = repoManager.openRepository(allUsers)) {
      return repo.getRefDatabase()
          .getRefsByPrefix(RefNames.refsDraftCommentsPrefix(getVirtualId(notes)));
    } catch (IOException e) {
      throw new StorageException(e);
    }
  }

  private List sort(List comments) {
    return CommentsUtil.sort(comments);
  }

  private Change.Id getVirtualId(ChangeNotes notes) {
    return virtualIdAlgorithm == null
        ? notes.getChangeId()
        : virtualIdAlgorithm.apply(notes.getServerId(), notes.getChangeId());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy