clientloguser.cpp #1

  • //
  • guest/
  • samwise/
  • p4hl/
  • src/
  • dlls/
  • clientloguser.cpp
  • View
  • Commits
  • Open Download .zip Download (6 KB)
// clientloguser.cpp: implementation of the clientloguser class.
//
//////////////////////////////////////////////////////////////////////

#include "clientloguser.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

ClientLogUser::ClientLogUser()
{

}

ClientLogUser::~ClientLogUser()
{

}

/* This is where the magic happens.
 * Lines of filelog output will have a level of '0', '1', or '2'.
 * Level '0' is the file name - we can ignore this.
 * Level '1' is a revision record, looking like this:
 * #2 change 767 edit on 2001/09/25 by samwise@samwise-luey (binary+k) 'description'
 * Level '2' is an integ record, looking like this:
 * branch from //depot/foo/bar#1,#2
 */

void ClientLogUser::OutputInfo(char level, const_char *data)
{
	/* Ignore level '0'. */
	/* If this is a rev record, create a new FileRev object for it. */
	if (level == '1')
	{
		StrBuf rev = StrBuf(); //this will be the rev number
		StrBuf change = StrBuf(); //this will be the change number
		short type; //this will be the revision type
		char* ptr = data+1; //skip over '#' - we're now pointing at the rev number
		while (*ptr != ' ') //go until we see the first space
		{
			rev.Append(ptr, 1);
			ptr++;
		} //rev now contains the rev number.
		ptr += 8; //skip over ' change ' - we're now pointing at the change number
		while (*ptr != ' ')
		{
			change.Append(ptr, 1);
			ptr++;
		} //change now contains the change number.
		ptr++; //skip the space - now looking at the rev type.
		switch (*ptr) //We can determine the rev type from the first letter alone unless it's an i.
		{
		default:
		case 'e': type = TYPE_EDIT; break; // 'edit'
		case 'a': type = TYPE_ADD; break; // 'add'
		case 'b': type = TYPE_BRANCH; break; // 'branch'
		case 'd': type = TYPE_DEL; break; // 'delete'
		case 'i': type = 0; break;  //indeterminate from first character
		}
		if (type == 0) //Was it an 'i'? 
		{
			ptr++;
			if (*ptr == 'm') type = TYPE_ADD; // 'import'
			else type = TYPE_INTEG; // 'integ'
		}
		working->addRev(rev, change, type); //Tell the FileHead to create a new FileRev.
		return; //All done with this line of output!
	}
	/* Here's where we handle integ records.*/
	if (level == '2')
	{
		short type; //This will be the integ type - different from rev type!
		char* ptr = data; //ptr is pointing at the first character of the integ type.
		switch (*ptr)
		{
		default:
		case 'm': type = TYPE_MERGE; break;  // 'merge'
		case 'b': type = TYPE_BRANCH; break; // 'branch'
		case 'e': type = TYPE_DIRTY; break;  // 'edit'
		case 'a': type = TYPE_DIRTY; break;  // 'add'
		case 'c': type = TYPE_COPY; break;   // 'copy'
		case 'i': type = TYPE_IGNORE; break; // 'ignored'
		}
		
		/* If the rev type is an "add", this is an "add into/from", even if the integ type
		 * is given as "branch".  The following line takes care of that.  It also takes
		 * care of the fact that older servers didn't have "edit from/into" records.  */
		if (working->tail->type == TYPE_ADD || 
			working->tail->type == TYPE_EDIT ) type = TYPE_DIRTY;

		while (*ptr != ' ') {ptr++;} //Skip past the rest of that word to the next space.
		ptr++; //Skip the space - the current word is either 'from' or 'into'.

		/* A "from" integ record will be indicated by the word "from" in most cases.
	     * For example, "merge from" or "branch from".  The exception is the word
		 * "ignored".  If this is the case, we'll be looking at a filespec rather
		 * than a "from" or "into". */
		if (*ptr == 'f' || *ptr == '/') // 'from' or the beginning of a filespec.
		{ //This is a "from" record, so note this in the appropriate FileRev.
			working->tail->fromtype = type; //This is the integ type.
			StrBuf filepath = StrBuf(); //This will be the "fromfile".
			StrBuf rev = StrBuf(); //This will be the "fromrev".

			if (*ptr == 'f') //If this word is "from", skip past it to the file.
			{

				while (*ptr != ' ') {ptr++;}
				ptr++; //now we're at the start of the "from" filespec
			}
			//If it wasn't, it was an "ignored" and we're there anyway.
			while (*ptr != '#') //scan up to the '#' revision marker.
			{
				filepath.Append(ptr, 1);
				ptr++;
			}
			working->tail->fromfile = filepath; //The fromfile has been set.
			ptr ++; //Skip over the '#'.  Now looking at a revision number.
			/* At this point we'll either see a single revision or a revision
			 * range.  If it's a revision range it'll be of the form:
			 * #12,#15
			 * whereas a single revision will just be
			 * #15
			 * If it's a range, we want to look at the last number in that range. */
			while ((*ptr != ',') && (*ptr != '\0'))
			{
				rev.Append(ptr, 1);
				ptr++;
			} //rev now contains either the single revision, or the first rev in a range.
			if (*ptr == '\0')  //Single revision - use it.
			{
				working->tail->fromrev = rev;
				return; //All done with this line.
			}
			rev = StrBuf();   //This isn't the end of the line, so there must be another rev.
			ptr+=2; //skip over ",#" to get to the start of the end rev.
			while (*ptr != '\0')
			{
				rev.Append(ptr, 1);
				ptr++;
			} //Now rev contains the end rev of the range.
			working->tail->fromrev = rev;
			return; //Done.
		}
		else // This line is an "into".
		{
			StrBuf filepath = StrBuf();
			StrBuf rev = StrBuf();
			while (*ptr != ' ') {ptr++;} //Skip over this word, be it "into" or "by".
			ptr++; //Skip the space - now we're at the start of an "into" filespec.
			while (*ptr != '#') //Go up to the '#' marker.
			{
				filepath.Append(ptr, 1);
				ptr++;
			} // We now have the "into" file.
			working->tail->intofiles.Append(filepath); //Store it in the FileRev.
			ptr++; //Skip the '#' and get to the revision.  This is not a range.
			while (*ptr != '\0')
			{
				rev.Append(ptr, 1);
				ptr++;
			}
			working->tail->intorevs.Append(rev); //Store the rev.
			return; //Done!
		}
	}
}

# Change User Description Committed
#2 937 Sam Stafford Renaming my guest directory to the more conventional
sam_stafford.
#1 936 Sam Stafford Adding P4HL to the public depot.
 See relnotes.txt for
installation instructions; all relevant files are under
p4hl/dist.

Source code is under p4hl/src in the form of a VC++ project.