#ifndef COMMON_CHANGE_H
#define COMMON_CHANGE_H

/*
 * Copyright (c) 2002, The EROS Group, LLC and Johns Hopkins
 * University. All rights reserved.
 * 
 * This software was developed to support the EROS secure operating
 * system project (http://www.eros-os.org). The latest version of
 * the OpenCM software can be found at http://www.opencm.org.
 * 
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. 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.
 * 
 * 3. Neither the name of the The EROS Group, LLC nor the name of
 *    Johns Hopkins University, 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.
 */

/* A Change is the result of a "commit" into a branch. Changes have
 * associated with them certain meta-information:
 *
 *    who created this configuration (a certificate)
 *    when the commit occurred (a time+date)
 *    the list of entities contained in the change
 *
 * Note that there is no "relative" or "delta" oriented
 * information. The "Change" object could as easily be called a
 * "Configuration".
 *
 * Note that the Change object is a purely internal data structure
 * within a Branch. To understand what goes on in the user's
 * workspace, see the PendingChange object.
 *
 * ISSUES:
 *
 * 1. EFFICIENCY
 *
 * While all of the above is logically part of a single record, it has
 * been split in the current implementation for reasons of reducing
 * data transfer. In order to reduce data transfer cost, we need to
 * reduce the overall size of the serialized Branch image.
 *
 * The common operations on Branches are CHECKOUT, COMMIT, HISTORY. Of
 * these, only CHECKOUT and COMMIT need to examine the actual entity
 * list. (DIFF similarly, but again examines only two entity
 * lists).  Therefore, we do not wish to incorporate the entity list
 * into the Change object.
 *
 * An alternative would be to incorporate into each Change object only
 * those entities that are new with that change. This has the
 * unfortunate property that there is no easy way to know how many
 * Change objects to fetch in order to reconstruct a complete
 * configuration. I've therefore concluded that this should be
 * considered a storage compression issue rather than a representation
 * issue.
 *
 * The other thing to consider externalizing is the history
 * records. For the moment, I have decided not to do this, because in
 * OPENCM the common usage will be to work on a private branch
 * constructed from a particular Change of particular predecessor. As
 * such, the description set of immediate relevance should be
 * relatively short. ** This introduces another issue, which is how to
 * help the user understand which things to replicate. I AM NOT
 * CONVINCED that this decision is the right one, but see below...
 * 
 * 2. SIZE OF BRANCH OVER LIFESPAN
 *
 * At some point, we will start to have branches that have very long
 * lifecycles. Even if we externalize both the description string and
 * the entity list, the resulting Change record would be about 100
 * bytes. Call it 128 to keep the arithmetic simple. The current EROS
 * OS repository has lines of development with tens of thousands of
 * changes, and these all by a single developer. 10,000 changes times
 * 128 bytes is 312k. Certainly more than I really want to download to
 * get started on a line of development. Adding the descriptions back
 * in makes it more. We therefore need a mechanism that lets us grab
 * some subset of the change records (probably the top N changes or
 * the most recent N days).
 *
 * 3. SYNCHRONIZATION/REPLICATION
 *
 * One hard question is: who owns the canonical branch? I.e. which
 * direction to replicate? I've come to the conclusion that there
 * should be ../my.branches and ../branches subdirs, but let's get the
 * local case right.
 *
 * I don't use time_t because it's not a universally agreed data
 * type. I therefore use string representation of time instead.
*/

struct Change {
  Serializable ser;

  const char *CMVAR(fileACLs);

 /* Description (for humans) of the commit. Referenced by all objects
  * that were created in a given commit operation. */
  const char *CMVAR(commitInfoTrueName);

  const char *CMVAR(parent);   /* preceding change (on same branch) */
  const char *CMVAR(mergeParent); /* merged change (if any) */

  OC_bool     CMVAR(isPartialMerge); /* if the merge change is incomplete */

  StrVec      *CMVAR(mergeHist); /* history of merges */

  ObVec       *CMVAR(entities);	/* in-lined entities in this Change */

  const char  *CMVAR(filterSetName); /* truename of per-branch fsname filter */
};

/* Caller should populate the remaining fields. These are never
 * optional. */
Change *
change_create(const char *parent, CommitInfo *ci);
void change_append_entity(Change *, const Entity *e);

#endif /* COMMON_CHANGE_H */
