/*
* C4 -- CVS like front end to the Perforce p4 SCM tool.
*
* Copyright (c) 1997, Neil Russell. All rights reserved.
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Neil Russell.
* 4. The name Neil Russell may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY NEIL RUSSELL ``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 NEIL RUSSELL 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.
*
* "p4 fstat" assimilation.
*/
#include "defs.h"
/**************************************************/
static void
fstat_func(char * l)
{
static File * fp;
static int headRev;
if (strncmp(l, "... clientFile ", 15) == 0)
{
if (fp)
Error(0, "clientFile seen twice in the same entry");
if (strncmp(&l[15], CurDir, CurDirLen) != 0)
Error(0, "clientFile is not a decendent of "
"the current directory (%s)", &l[15]);
/*
* Lookup the name using the relative path (strip the
* current directory portion, including the '/').
* Create the entry if it doesn't exist (actually, if
* it exists, something is wrong with "p4 fstat").
*/
fp = Lookup(&l[15 + CurDirLen + 1], 1);
headRev = 0;
}
if (fp)
{
if (strncmp(l, "... headAction", 14) == 0)
{
if (strncmp(l, "... headAction delete", 21) != 0)
fp->flag |= F_DEPOT;
}
else if (strncmp(l, "... haveTime ", 13) == 0)
{
/*
* Since 97.2, p4 produces a field called
* "headTime", which is the time the file
* in the client was last submitted. If the
* client flag "modtime" is set, then this
* time could be used to determine if the file
* had been modified. If the "modtime" flag
* is set however, it breaks "make". Also,
* p4 does not guarentee that the modtime of
* the file equals the headTime, even if the
* "modtime" flag is set (I think).
*
* What we really need is for perforce to tell
* us that the modtime of the file should be
* based on the last operation that effected
* it (effectively a "haveTime". This would
* require a database of times for each file
* for each client, something that Perforce
* says is possible (there is already a database
* for stuff for each client for things like
* "haveRev"), but hard, because the database
* file format would have to change as would
* parts of the client/server protocol. So
* for now, we will try to get the "haveTime",
* and arange for the modtime we store to be
* zero if the "haveTime" field doesn't exist.
* This will degrade to a "p4 diff" being run
* on every file. Ther performance of this
* diff is fairly good, so this is not too bad.
* If "haveTime" was available, you could expect
* something like a four times speed improvement,
* maybe a lot more. During a scan, every file
* must be stat'ed, but a "p4 diff" on every
* file requires every file to be read.
*/
fp->modtime = atol(&l[13]);
}
else if (strncmp(l, "... headRev ", 12) == 0)
headRev = atoi(&l[12]);
else if (strncmp(l, "... haveRev ", 12) == 0)
{
/*
* "haveRev" means that we have the file.
* If the rev is different than "headRev",
* then the file needs a get. We rely on
* getting "headRev" before "haveRev".
*/
fp->flag |= F_HAVE;
if (headRev != atoi(&l[12]))
fp->flag |= F_GET;
}
else if (strncmp(l, "... headType symlink ", 21) == 0)
fp->flag |= F_SYMLINK;
else if (strncmp(l, "... action edit", 15) == 0 ||
strncmp(l, "... action add", 14) == 0)
fp->flag |= F_OPEN;
else if (strncmp(l, "... action delete", 17) == 0)
fp->flag |= F_DELETE;
#if 0
else if (strncmp(l, "... change ", 11) == 0)
fp->change = atoi(&l[11]);
#endif
else if (!*l) /* Empty line is end of entry */
{
fp = (File *)0;
}
}
}
void
DoFstat(void)
{
Command("fstat ...", fstat_func, 0);
CommandDone();
PrintTree("fstat");
}