rcsmeta.cc #1

  • //
  • guest/
  • perforce_software/
  • p4/
  • 2014-2/
  • rcs/
  • rcsmeta.cc
  • View
  • Commits
  • Open Download .zip Download (7 KB)
/*
 * Copyright 1995, 1996 Perforce Software.  All rights reserved.
 *
 * This file is part of the Library RCS.  See rcstest.c.
 */

/*
 * rcsmeta.c - print out RCS metadata, given an RcsArchive structure
 *
 * Classes defined:
 *
 *	RcsGenMeta - control block for generating metadata
 *
 * Public methods:
 *
 *	RcsGenMeta::RcsGenMeta -- set up for metadata generation
 *	RcsGenMeta::Generate - write metadata to stdio file
 *
 * Private structures:
 *
 *	RcsRevMeta - metadata info about a single rev
 *
 * History:
 *	2-18-97 (seiwald) - translated to C++.
 */

# define NEED_TYPES

# include <stdhdrs.h>

# include <strbuf.h>
# include <error.h>
# include <errorlog.h>
# include <filesys.h>

# include "readfile.h"
# include "rcsarch.h"
# include "rcsrev.h"
# include "rcsgen.h"
# include "rcsdate.h"
# include "rcsmeta.h"

/* CHEAT! from dmtypes.h! */

enum DmtActionType {
	DAT_ADD 	= 0,
	DAT_EDIT 	= 1,
	DAT_DELETE 	= 2,
	DAT_BRANCH	= 3,
	DAT_INTEG	= 4
} ;

/*
 * Generate output of the form:
 *
 *   rev:
 *	"rev" //depot/branch/path rev ishead action 
 *	      change-date change-code change-user 
 *	      //depot/IMPORT/arch-path arch-rev
 *
 *   label:
 *	"label" label //label/branch/path //depot/branch/path rev change-date
 *
 *   change:
 *	"change" change-date change-code change-user @text@
 *
 */


struct RcsRevMeta
{
	const char	*branch;
	const char	*revName;
	int		revNum;
	int		isHead;
	int		action;
} ;

RcsGenMeta::RcsGenMeta(
	FileSys *wf, 
	RcsArchive *ar,
	char *archName )
{
	this->wf = wf;
	this->ar = ar;
	this->archName = archName;

	/* In the attic? */

	char *a = archName;

	while( ( a = strchr( a, 'A' ) ) && strncmp( a, "Attic/", 6 ) )
		++a;

	if( isDead = ( a != 0 ) )
	{
	    strncpy( path, archName, a - archName );
	    strcpy( path + ( a - archName ), a + 6 );
	}
	else
	{
	    strcpy( path, archName );
	}
}

void
RcsGenMeta::Generate(
	Error *e )
{
	RcsRevMeta	rm;

	/* (Recursively) dump out the trunk */

	rm.branch = "main";
	rm.revName = ar->headRev.text;
	rm.isHead = 1;
	rm.revNum = 1;
	rm.action = DAT_ADD;

	Trunk( &rm, e );

	AssertLog.Report( e );
}

void
RcsGenMeta::Trunk(
	RcsRevMeta *rm,
	Error *e )
{
	RcsRev *rev;

	/* Find the rev */

	rev = ar->FindRevision( rm->revName, e );

	if( e->Test() )
	    return;

	/* Figure action */

	rm->action = DAT_EDIT;

	/* Recurse, to count down to the trunk. */

	if( rev->next.text )
	{
	    RcsRevMeta nrm[1];

	    nrm->branch = rm->branch;
	    nrm->isHead = 0;
	    nrm->revName = rev->next.text;
	    nrm->revNum = 1;
	    nrm->action = DAT_EDIT;	/* reset later */
	    Trunk( nrm, e );
	    rm->revNum += nrm->revNum;

	    if( e->Test() )
		return;

	    /* If nrm shows the previous rev was deleted, we'll make this */
	    /* rev an add. */

	    if( nrm->action == DAT_DELETE )
		rm->action = DAT_ADD;
	}
	else
	{
	    rm->action = DAT_ADD;
	}

	/* Dump out this rev. */

	Rev( rm, rev );

	/* Now, dump out branches */

	Branches( rm, rev, e );
}

void
RcsGenMeta::Branch(
	RcsRevMeta *rm,
	Error *e )
{
	RcsRev *rev;

	/* Find the rev */

	rev = ar->FindRevision( rm->revName, e );

	if( e->Test() )
	    return;

	/* Action always EDIT, since BRANCH is handled by RcsMetaBranches */
	/* actually, always EDIT */

	rm->isHead = !rev->next.text;
	rm->action = DAT_EDIT;

	/* Dump out this rev. */

	Rev( rm, rev );

	/* Now, dump out branches */

	Branches( rm, rev, e );

	if( e->Test() )
	    return;

	/* Recurse to next */

	if( rev->next.text )
	{
	    RcsRevMeta nrm[1];

	    nrm->branch = rm->branch;
	    nrm->revName = rev->next.text;
	    nrm->revNum = rm->revNum + 1;
	    /* isHead computed later */
	    /* action computed later */

	    Branch( nrm, e );
	}
}

void
RcsGenMeta::Branches(
	RcsRevMeta *rm,
	RcsRev *rev, 
	Error *e )
{
	RcsList *s;

	for( s = rev->branches; s; s = s->qNext )
	{
	    RcsList *t;
	    RcsRevMeta nrm[1];
	    char *r = s->revision.text;

	    /* Find the symbol for this branch */

	    for( t = ar->symbolList; t; t = t->qNext )
		if( RcsRevCmp( r, t->revision.text ) == REV_CMP_NUM_BRANCH )
		    break;

	    if( !t )
	    {
		fprintf( stderr, "%s/%s has no branch\n", archName, r );
		continue;
	    }

	    /* Generate branch point -- sames as orig */

	    nrm->branch = t->string.text;
	    nrm->revName = rm->revName;
	    nrm->revNum = 1;
	    nrm->isHead = 0;
	    nrm->action = DAT_BRANCH;

	    Rev( nrm, rev );

	    /* Now generate remaining revs 2+ in branch */

	    nrm->branch = t->string.text;
	    nrm->revName = s->revision.text;
	    nrm->revNum = 2;
	    nrm->isHead = 0;		/* dummy */
	    nrm->action = DAT_EDIT;	/* dummy */

	    Branch( nrm, e );

	    if( e->Test() )
		return;

	    /* Generate integration record & reverse integ record. */

	    GenString( "integ" );
	    File3( "depot", t->string.text, path ); /* to */
	    File3( "depot", rm->branch, path ); /* from */
	    GenNum( 0 );	/* startFromRev */
	    GenNum( rm->revNum );	/* endFromRev */
	    GenNum( 1 );	/* toRev */
	    GenNum( 2 );	/* BRANCH */
	    GenNum( 1 );	/* commited */
	    GenNum( 1 );	/* resolved */
	    GenNum( 0 );	/* changeCode */
	    GenNL();

	    GenString( "integ" );
	    File3( "depot", rm->branch, path ); /* from */
	    File3( "depot", t->string.text, path ); /* to */
	    GenNum( 0 );	/* startFromRev */
	    GenNum( 1 );	/* endFromRev */
	    GenNum( rm->revNum );	/* toRev */
	    GenNum( 3 );	/* BRANCH_R */
	    GenNum( 1 );	/* commited */
	    GenNum( 1 );	/* resolved */
	    GenNum( 0 );	/* changeCode */
	    GenNL();
	}
}

void
RcsGenMeta::Rev(
	RcsRevMeta *rm,
	RcsRev *rev )
{
	/* Dump out a revision */

	RcsList *s;
	int changeDate;
	unsigned int changeCode;
	RcsDate date;

	/* Turn action of "dead" rev's into delete. */

    	if( !strcmp( rev->state.text, "dead" ) || isDead && rm->isHead )
		rm->action = DAT_DELETE;

	/* Hash the change text. */

	{
	    RcsSize len;
	    changeCode = 0;

	    rev->log.file->Seek( rev->log.offset );

	    for( len = rev->log.length; len && !rev->log.file->Eof(); --len )
	    {
		changeCode = ( changeCode * 2903657531u ) 
			     ^ rev->log.file->Char() ;
		rev->log.file->Next();
	    }
	}

	/* And get the date */

	date.Set( rev->date.text );
	changeDate = date.Parse();

	/* Dump change */

	GenString( "change" );
	GenNum( changeDate );
	GenNum( changeCode );
	GenString( rev->author.text );
	GenChunk( &rev->log, 0 );
	GenNL();

	/* Dump rev */

	GenString( "rev" );
	File3( "depot", rm->branch, path );
	GenNum( rm->revNum );
	GenNum( rm->isHead );
	GenNum( rm->action );
	GenNum( changeDate );
	File3( "depot", "IMPORT", archName );
	GenString( rev->revName.text );
	GenNum( changeCode );
	GenString( rev->author.text );
	GenNL();

	/* Dump labels if there are any. */

	for( s = ar->symbolList; s; s = s->qNext )
	{
	    char label[ 64 ]; /* XXX DmtLDomain */

	    switch( RcsRevCmp( rev->revName.text, s->revision.text ) )
	    {
	    case REV_CMP_EQUAL:
		/* Truncate label at 63 chars */

		strncpy( label, s->string.text, sizeof( label ) );
		label[sizeof(label)-1] = 0;

		/* Symbol for this rev - write label entry */
		GenString( "label" );
		GenString( label );
		File3( label, rm->branch, path );
		File3( "depot", rm->branch, path );
		GenNum( rm->revNum );
		GenNum( changeDate );
		GenNL();
		break;
	    }
	}
}

void
RcsGenMeta::File3( 
	const char *domain,
	const char *branch,
	const char *path )
{
	char buf[1024];
	sprintf( buf, "//%s/%s/%s", domain, branch, path );
	GenString( buf );
}
# Change User Description Committed
#1 15903 Matt Attaway Everything should be happy now between the Workshop and the depot paths
//guest/perforce_software/p4/2014_2/rcs/rcsmeta.cc
#1 15901 Matt Attaway Clean up code to fit modern Workshop naming standards
//guest/perforce_software/p4/2014.2/rcs/rcsmeta.cc
#1 12189 Matt Attaway Initial (and much belated) drop of 2014.2 p4 source code