com.google.gerrit.pgm.ExportReviewNotes.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gerrit.pgm.ExportReviewNotes.java

Source

// Copyright (C) 2010 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.pgm;

import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;

import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.account.AccountCacheImpl;
import com.google.gerrit.server.account.GroupCacheImpl;
import com.google.gerrit.server.cache.CachePool;
import com.google.gerrit.server.config.ApprovalTypesProvider;
import com.google.gerrit.server.config.AuthConfigModule;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.CanonicalWebUrlProvider;
import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.git.CodeReviewNoteCreationException;
import com.google.gerrit.server.git.CreateCodeReviewNotes;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Scopes;

import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.lib.ThreadSafeProgressMonitor;
import org.eclipse.jgit.util.BlockList;
import org.kohsuke.args4j.Option;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/** Export review notes for all submitted changes in all projects. */
public class ExportReviewNotes extends SiteProgram {
    @Option(name = "--threads", usage = "Number of concurrent threads to run")
    private int threads = 2;

    private final LifecycleManager manager = new LifecycleManager();
    private final TextProgressMonitor textMonitor = new TextProgressMonitor();
    private final ThreadSafeProgressMonitor monitor = new ThreadSafeProgressMonitor(textMonitor);

    private Injector dbInjector;
    private Injector gitInjector;

    @Inject
    private GitRepositoryManager gitManager;

    @Inject
    private SchemaFactory<ReviewDb> database;

    @Inject
    private CreateCodeReviewNotes.Factory codeReviewNotesFactory;

    private Map<Project.NameKey, List<Change>> changes;

    @Override
    public int run() throws Exception {
        if (threads <= 0) {
            threads = 1;
        }

        dbInjector = createDbInjector(MULTI_USER);
        gitInjector = dbInjector.createChildInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(ApprovalTypes.class).toProvider(ApprovalTypesProvider.class).in(Scopes.SINGLETON);
                bind(String.class).annotatedWith(CanonicalWebUrl.class).toProvider(CanonicalWebUrlProvider.class)
                        .in(Scopes.SINGLETON);
                bind(CachePool.class);

                install(AccountCacheImpl.module());
                install(GroupCacheImpl.module());
                install(new AuthConfigModule());
                install(new FactoryModule() {
                    @Override
                    protected void configure() {
                        factory(CreateCodeReviewNotes.Factory.class);
                    }
                });
                install(new LifecycleModule() {
                    @Override
                    protected void configure() {
                        listener().to(CachePool.Lifecycle.class);
                        listener().to(LocalDiskRepositoryManager.Lifecycle.class);
                    }
                });
            }
        });

        manager.add(dbInjector, gitInjector);
        manager.start();
        gitInjector.injectMembers(this);

        List<Change> allChangeList = allChanges();
        monitor.beginTask("Scanning changes", allChangeList.size());
        changes = cluster(allChangeList);
        allChangeList = null;

        monitor.startWorkers(threads);
        for (int tid = 0; tid < threads; tid++) {
            new Worker().start();
        }
        monitor.waitForCompletion();
        monitor.endTask();
        manager.stop();
        return 0;
    }

    private List<Change> allChanges() throws OrmException {
        final ReviewDb db = database.open();
        try {
            return db.changes().all().toList();
        } finally {
            db.close();
        }
    }

    private Map<Project.NameKey, List<Change>> cluster(List<Change> changes) {
        HashMap<Project.NameKey, List<Change>> m = new HashMap<Project.NameKey, List<Change>>();
        for (Change change : changes) {
            if (change.getStatus() == Change.Status.MERGED) {
                List<Change> l = m.get(change.getProject());
                if (l == null) {
                    l = new BlockList<Change>();
                    m.put(change.getProject(), l);
                }
                l.add(change);
            } else {
                monitor.update(1);
            }
        }
        return m;
    }

    private void export(ReviewDb db, Project.NameKey project, List<Change> changes)
            throws IOException, OrmException, CodeReviewNoteCreationException, InterruptedException {
        final Repository git;
        try {
            git = gitManager.openRepository(project);
        } catch (RepositoryNotFoundException e) {
            return;
        }
        try {
            CreateCodeReviewNotes notes = codeReviewNotesFactory.create(db, git);
            try {
                notes.loadBase();
                for (Change change : changes) {
                    monitor.update(1);
                    PatchSet ps = db.patchSets().get(change.currentPatchSetId());
                    if (ps == null) {
                        continue;
                    }
                    notes.add(change, ObjectId.fromString(ps.getRevision().get()));
                }
                notes.commit("Exported prior reviews from Gerrit Code Review\n");
                notes.updateRef();
            } finally {
                notes.release();
            }
        } finally {
            git.close();
        }
    }

    private Map.Entry<Project.NameKey, List<Change>> next() {
        synchronized (changes) {
            if (changes.isEmpty()) {
                return null;
            }

            final Project.NameKey name = changes.keySet().iterator().next();
            final List<Change> list = changes.remove(name);
            return new Map.Entry<Project.NameKey, List<Change>>() {
                @Override
                public Project.NameKey getKey() {
                    return name;
                }

                @Override
                public List<Change> getValue() {
                    return list;
                }

                @Override
                public List<Change> setValue(List<Change> value) {
                    throw new UnsupportedOperationException();
                }
            };
        }
    }

    private class Worker extends Thread {
        @Override
        public void run() {
            ReviewDb db;
            try {
                db = database.open();
            } catch (OrmException e) {
                e.printStackTrace();
                return;
            }
            try {
                for (;;) {
                    Entry<Project.NameKey, List<Change>> next = next();
                    if (next != null) {
                        try {
                            export(db, next.getKey(), next.getValue());
                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (OrmException e) {
                            e.printStackTrace();
                        } catch (CodeReviewNoteCreationException e) {
                            e.printStackTrace();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        break;
                    }
                }
            } finally {
                monitor.endWorker();
                db.close();
            }
        }
    }
}