ListProjects.java :  » android-core » tools-gerrit » com » google » gerrit » sshd » commands » Android Open Source

Android Open Source » android core » tools gerrit 
tools gerrit » com » google » gerrit » sshd » commands » ListProjects.java
// Copyright (C) 2009 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.sshd.commands;

import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.WildProjectName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.sshd.BaseCommand;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;

import org.apache.sshd.server.Environment;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.kohsuke.args4j.Option;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

final class ListProjects extends BaseCommand {
  private static final String NODE_PREFIX = "|-- ";
  private static final String LAST_NODE_PREFIX = "`-- ";
  private static final String DEFAULT_TAB_SEPARATOR = "|";
  private static final String NOT_VISIBLE_PROJECT = "(x)";

  @Inject
  private ReviewDb db;

  @Inject
  private IdentifiedUser currentUser;

  @Inject
  private ProjectCache projectCache;

  @Inject
  private GitRepositoryManager repoManager;

  @Inject
  @WildProjectName
  private Project.NameKey wildProject;

  @Option(name = "--show-branch", aliases = {"-b"}, usage = "displays the sha of each project in the specified branch")
  private String showBranch;

  @Option(name = "--tree", aliases = {"-t"}, usage = "displays project inheritance in a tree-like format\n" +
      "this option does not work together with the show-branch option")
  private boolean showTree;

  private String currentTabSeparator = DEFAULT_TAB_SEPARATOR;

  @Override
  public void start(final Environment env) {
    startThread(new CommandRunnable() {
      @Override
      public void run() throws Exception {
        parseCommandLine();
        ListProjects.this.display();
      }
    });
  }

  private void display() throws Failure {
    if (showTree && (showBranch != null)) {
      throw new UnloggedFailure(1, "fatal: --tree and --show-branch options are not compatible.");
    }

    final PrintWriter stdout = toPrintWriter(out);

    TreeMap<String, TreeNode> treeMap = null;

    if (showTree) {
      treeMap = new TreeMap<String, TreeNode>();
    }

    try {
      for (final Project p : db.projects().all()) {
        if (p.getNameKey().equals(wildProject)) {
          // This project "doesn't exist". At least not as a repository.
          //
          continue;
        }

        final ProjectState e = projectCache.get(p.getNameKey());
        if (e == null) {
          // If we can't get it from the cache, pretend its not present.
          //
          continue;
        }

        final ProjectControl pctl = e.controlFor(currentUser);

        if (!showTree) {

          if (!pctl.isVisible()) {
            // Require the project itself to be visible to the user.
            //
            continue;
          }

          if (showBranch != null) {
            final Ref ref = getBranchRef(p.getNameKey());
            if (ref == null || ref.getObjectId() == null
                || !pctl.controlForRef(ref.getLeaf().getName()).isVisible()) {
              // No branch, or the user can't see this branch, so skip it.
              //
              continue;
            }

            stdout.print(ref.getObjectId().name());
            stdout.print(' ');
          }

          stdout.print(p.getName() + "\n");
        } else {
          treeMap.put(p.getName(), new TreeNode(p, pctl.isVisible()));
        }
      }

      if (showTree && treeMap.size() > 0) {
        final List<TreeNode> sortedNodes = new ArrayList<TreeNode>();

        // Builds the inheritance tree using a list.
        //
        for (final TreeNode key : treeMap.values()) {
          final String parentName = key.getParentName();
          if (parentName != null) {
            final TreeNode node = treeMap.get((String)parentName);
            if (node != null) {
              node.addChild(key);
            } else {
              sortedNodes.add(key);
            }
          } else {
            sortedNodes.add(key);
          }
        }

        // Builds a fake root node, which contains the sorted projects.
        //
        final TreeNode fakeRoot = new TreeNode(null, sortedNodes, false);
        printElement(stdout, fakeRoot, -1, false, sortedNodes.get(sortedNodes.size() - 1));
        stdout.flush();
      }
    } catch (OrmException e) {
      throw new Failure(1, "fatal: database error", e);
    } finally {
      stdout.flush();
    }
  }

  private Ref getBranchRef(Project.NameKey projectName) {
    try {
      final Repository r = repoManager.openRepository(projectName);
      try {
        return r.getRef(showBranch);
      } finally {
        r.close();
      }
    } catch (IOException ioe) {
      return null;
    }
  }

  /** Class created to manipulate the nodes of the project inheritance tree **/
  private static class TreeNode {
    private final List<TreeNode> children;
    private final Project project;
    private final boolean isVisible;

    /**
     * Constructor
     * @param p Project
     */
    public TreeNode(Project p, boolean visible) {
      this.children = new ArrayList<TreeNode>();
      this.project = p;
      this.isVisible = visible;
    }

    /**
     * Constructor used for creating the fake node
     * @param p Project
     * @param c List of nodes
     */
    public TreeNode(Project p, List<TreeNode> c, boolean visible) {
      this.children = c;
      this.project = p;
      this.isVisible = visible;
    }

    /**
     * Returns if the the node is leaf
     * @return True if is lead, false, otherwise
     */
    public boolean isLeaf() {
      return children.size() == 0;
    }

    /**
     * Returns the project parent name
     * @return Project parent name
     */
    public String getParentName() {
      if (project.getParent() != null) {
        return project.getParent().get();
      }

      return null;
    }

    /**
     * Adds a child to the list
     * @param node TreeNode child
     */
    public void addChild(TreeNode node) {
      children.add(node);
    }

    /**
     * Returns the project instance
     * @return Project instance
     */
    public Project getProject() {
      return project;
    }

    /**
     * Returns the list of children nodes
     * @return List of children nodes
     */
    public List<TreeNode> getChildren() {
      return children;
    }

    /**
     * Returns if the project is visible to the user
     * @return True if is visible, false, otherwise
     */
    public boolean isVisible() {
      return isVisible;
    }
  }

  /**
   * Used to display the project inheritance tree recursively
   * @param stdout PrintWriter used do print
   * @param node Tree node
   * @param level Current level of the tree
   * @param isLast True, if is the last node of a level, false, otherwise
   * @param lastParentNode Last "root" parent node
   */
  private void printElement(final PrintWriter stdout, TreeNode node, int level, boolean isLast,
      final TreeNode lastParentNode) {
    // Checks if is not the "fake" root project.
    //
    if (node.getProject() != null) {

      // Check if is not the last "root" parent node,
      // so the "|" separator will not longer be needed.
      //
      if (!currentTabSeparator.equals(" ")) {
        final String nodeProject = node.getProject().getName();
        final String lastParentProject = lastParentNode.getProject().getName();

        if (nodeProject.equals(lastParentProject)) {
          currentTabSeparator = " ";
        }
      }

      if (level > 0) {
        stdout.print(String.format("%-" + 4 * level + "s", currentTabSeparator));
      }

      final String prefix = isLast ? LAST_NODE_PREFIX : NODE_PREFIX ;

      String printout;

      if (node.isVisible()) {
        printout = prefix + node.getProject().getName();
      } else {
        printout = prefix + NOT_VISIBLE_PROJECT;
      }

      stdout.print(printout + "\n");
    }

    if (node.isLeaf()) {
      return;
    } else {
      final List<TreeNode> children = node.getChildren();
      ++level;
      for(TreeNode treeNode : children) {
        final boolean isLastIndex = children.indexOf(treeNode) == children.size() - 1;
        printElement(stdout, treeNode, level, isLastIndex, lastParentNode);
      }
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.