/* * Copyright (C) 2010, Google Inc. * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available * under the terms of the Eclipse Distribution License v1.0 which * accompanies this distribution, is reproduced below, and is * available at http://www.eclipse.org/org/documents/edl-v10.php * * All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * - Neither the name of the Eclipse Foundation, Inc. nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.eclipse.jgit.iplog; import java.io.File; import java.io.IOException; import java.net.URL; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.storage.file.LockFile; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; /** * Manages the {@code .eclipse_iplog} file in a project. */ public class IpLogMeta { /** Default name of the {@code .eclipse_iplog} file. */ public static final String IPLOG_CONFIG_FILE = ".eclipse_iplog"; private static final String S_PROJECT = "project"; private static final String S_CQ = "CQ"; private static final String S_CONSUMES = "consumes"; private static final String S_REVIEW = "review"; private static final String K_URL = "url"; private static final String K_NAME = "name"; private static final String K_VERSION = "version"; private static final String K_COMMENTS = "comments"; private static final String K_SKIP_COMMIT = "skipCommit"; private static final String K_LICENSE = "license"; private static final String K_DESCRIPTION = "description"; private static final String K_USE = "use"; private static final String K_STATE = "state"; private List projects = new ArrayList(); private List consumedProjects = new ArrayList(); private Set cqs = new HashSet(); private String reviewUrl; List getProjects() { return projects; } List getConsumedProjects() { return consumedProjects; } Set getCQs() { return cqs; } String getReviewUrl() { return reviewUrl; } void loadFrom(Config cfg) { projects.clear(); consumedProjects.clear(); cqs.clear(); projects.addAll(parseProjects(cfg, S_PROJECT)); consumedProjects.addAll(parseProjects(cfg, S_CONSUMES)); for (String id : cfg.getSubsections(S_CQ)) { CQ cq = new CQ(Long.parseLong(id)); cq.setDescription(cfg.getString(S_CQ, id, K_DESCRIPTION)); cq.setLicense(cfg.getString(S_CQ, id, K_LICENSE)); cq.setUse(cfg.getString(S_CQ, id, K_USE)); cq.setState(cfg.getString(S_CQ, id, K_STATE)); cq.setComments(cfg.getString(S_CQ, id, K_COMMENTS)); cqs.add(cq); } reviewUrl = cfg.getString(S_REVIEW, null, K_URL); } private List parseProjects(final Config cfg, final String sectionName) { final List dst = new ArrayList(); for (String id : cfg.getSubsections(sectionName)) { String name = cfg.getString(sectionName, id, K_NAME); Project project = new Project(id, name); project.setVersion(cfg.getString(sectionName, id, K_VERSION)); project.setComments(cfg.getString(sectionName, id, K_COMMENTS)); for (String c : cfg.getStringList(sectionName, id, K_SKIP_COMMIT)) project.addSkipCommit(ObjectId.fromString(c)); for (String license : cfg.getStringList(sectionName, id, K_LICENSE)) project.addLicense(license); dst.add(project); } return dst; } /** * Query the Eclipse Foundation's IPzilla database for CQ records. *

* Updates the local {@code .eclipse_iplog} configuration file with current * information by deleting CQs which are no longer relevant, and adding or * updating any CQs which currently exist in the database. * * @param file * local file to update with current CQ records. * @param fs * the file system abstraction which will be necessary to perform * certain file system operations. * @param base * base https:// URL of the IPzilla server. * @param username * username to login to IPzilla as. Must be a Bugzilla username * of someone authorized to query the project's IPzilla records. * @param password * password for {@code username}. * @throws IOException * IPzilla cannot be queried, or the local file cannot be read * from or written to. * @throws ConfigInvalidException * the local file cannot be read, as it is not a valid * configuration file format. */ public void syncCQs(File file, FS fs, URL base, String username, String password) throws IOException, ConfigInvalidException { FileUtils.mkdirs(file.getParentFile(), true); LockFile lf = new LockFile(file, fs); if (!lf.lock()) throw new IOException(MessageFormat.format(IpLogText.get().cannotLock, file)); try { FileBasedConfig cfg = new FileBasedConfig(file, fs); cfg.load(); loadFrom(cfg); IPZillaQuery ipzilla = new IPZillaQuery(base, username, password); Set current = ipzilla.getCQs(projects); for (CQ cq : sort(current, CQ.COMPARATOR)) { String id = Long.toString(cq.getID()); set(cfg, S_CQ, id, K_DESCRIPTION, cq.getDescription()); set(cfg, S_CQ, id, K_LICENSE, cq.getLicense()); set(cfg, S_CQ, id, K_USE, cq.getUse()); set(cfg, S_CQ, id, K_STATE, cq.getState()); set(cfg, S_CQ, id, K_COMMENTS, cq.getComments()); } for (CQ cq : cqs) { if (!current.contains(cq)) cfg.unsetSection(S_CQ, Long.toString(cq.getID())); } lf.write(Constants.encode(cfg.toText())); if (!lf.commit()) throw new IOException(MessageFormat.format(IpLogText.get().cannotWrite, file)); } finally { lf.unlock(); } } private static void set(Config cfg, String section, String subsection, String key, String value) { if (value == null || "".equals(value)) cfg.unset(section, subsection, key); else cfg.setString(section, subsection, key, value); } private static > Iterable sort( Collection objs, Q cmp) { ArrayList sorted = new ArrayList(objs); Collections.sort(sorted, cmp); return sorted; } }