398 lines
9.4 KiB
C
398 lines
9.4 KiB
C
/* in - checkin the specified files */
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "messages.h"
|
|
EnableAssert
|
|
|
|
private void IgnMarked(P1(AD *));
|
|
private void IgnFi(P3(AD *, FI far *, FS far *));
|
|
private void UnMarkIn(P2(AD *, NE *));
|
|
private F FInMarked(P2(AD *, F *));
|
|
private F FInOutFile(P3(AD *pad, FI far *pfi, FS far *pfs));
|
|
|
|
int SpawnFilter(P7(char *, char *, char *, char *, char *,int, char *));
|
|
|
|
|
|
|
|
F
|
|
FInInit(
|
|
AD *pad)
|
|
{
|
|
CheckProjectDiskSpace(pad, cbProjectFreeMin);
|
|
|
|
/* check arguments' validity */
|
|
if (pad->pneArgs && pad->flags&flagAllOut)
|
|
{
|
|
Error("must specify either files or -o\n");
|
|
Usage(pad);
|
|
}
|
|
|
|
/* if in -a, just check in files that are out */
|
|
if (pad->flags & flagAll)
|
|
pad->flags |= flagAllOut;
|
|
|
|
if ((pad->flags&flagIgnChanges))
|
|
{
|
|
if (pad->flags&flagInUpdate)
|
|
{
|
|
Error("-i together with -u has no effect\n");
|
|
Usage(pad);
|
|
}
|
|
else if (pad->szComment || pad->flags&(flagInChecKpt|flagInDashB|flagInDashZ))
|
|
{
|
|
Error("-i ignores changes, incompatible with -%c\n",
|
|
pad->szComment ? 'c' :
|
|
(pad->flags&flagInChecKpt) ? 'k' :
|
|
(pad->flags&flagInDashB) ? 'b' : 'z');
|
|
Usage(pad);
|
|
}
|
|
}
|
|
|
|
/* If in -o, clear fFiles flag, so we are called for each directory,
|
|
* with an empty pad->pneFiles.
|
|
*/
|
|
if (pad->flags&flagAllOut)
|
|
pad->pecmd->gl &= ~fglFiles;
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/* perform In operation for this directory */
|
|
F
|
|
FInDir(
|
|
AD *pad)
|
|
{
|
|
F fOk = fTrue;
|
|
F fAny = fFalse;
|
|
|
|
if (!FLoadStatus(pad, lckAll, flsNone) || !FHaveCurDir(pad))
|
|
return fFalse;
|
|
|
|
if (pad->pneFiles != 0)
|
|
MarkList(pad, pad->pneFiles, fTrue);
|
|
else
|
|
{
|
|
AssertF(pad->flags&flagAllOut);
|
|
MarkOut(pad, pad->iedCur);
|
|
}
|
|
|
|
UnMarkIn(pad, pad->pneFiles); /* unmark if file already in */
|
|
|
|
if (pad->flags&flagIgnChanges)
|
|
IgnMarked(pad);
|
|
|
|
else if (!(fOk = FSyncMarked(pad, NULL)))
|
|
Error("no files checked in for %!&/U/Q\n", pad);
|
|
|
|
else
|
|
{
|
|
OpenLog(pad, fTrue);
|
|
|
|
fOk = FInMarked(pad, &fAny);
|
|
|
|
CloseLog();
|
|
|
|
if (fAny)
|
|
ProjectChanged(pad);
|
|
|
|
SyncVerH(pad, NULL);
|
|
}
|
|
|
|
FlushStatus(pad);
|
|
|
|
return fOk;
|
|
}
|
|
|
|
|
|
/* Unmark those files in pneFiles which are not checked out.
|
|
* This will unmark fmIn and fmCopyIn modes so that they will not
|
|
* get ssynced.
|
|
*/
|
|
private void
|
|
UnMarkIn(
|
|
AD *pad,
|
|
NE *pneFiles)
|
|
{
|
|
NE *pne;
|
|
FI far *pfi;
|
|
FS far *pfs;
|
|
F fExists;
|
|
|
|
ForEachNe(pne, pneFiles)
|
|
{
|
|
if (!FLookupSz(pad, SzOfNe(pne), &pfi, &fExists))
|
|
{
|
|
Warn("%&C/%s does not exist\n", pad, SzOfNe(pne));
|
|
continue;
|
|
}
|
|
|
|
pfs = PfsForPfi(pad, pad->iedCur, pfi);
|
|
|
|
switch (pfs->fm)
|
|
{
|
|
default:
|
|
FatalError(szBadFileFormat, pad, pfi);
|
|
|
|
case fmIn:
|
|
case fmCopyIn:
|
|
Warn("%&C/%s is already checked in\n", pad, SzOfNe(pne));
|
|
pfi->fMarked = fFalse;
|
|
break;
|
|
|
|
case fmAdd:
|
|
case fmGhost:
|
|
case fmDelIn:
|
|
case fmDelOut:
|
|
case fmOut:
|
|
case fmMerge:
|
|
case fmVerify:
|
|
case fmConflict:
|
|
case fmNonExistent:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* check in the marked files, ignoring changes */
|
|
private void
|
|
IgnMarked(
|
|
AD *pad)
|
|
{
|
|
FI far *pfi;
|
|
FI far *pfiMac;
|
|
|
|
for (pfi = pad->rgfi, pfiMac=pfi+pad->psh->ifiMac; pfi < pfiMac; pfi++)
|
|
{
|
|
if (pfi->fMarked)
|
|
IgnFi(pad, pfi, PfsForPfi(pad, pad->iedCur, pfi));
|
|
}
|
|
}
|
|
|
|
|
|
/* in -i one file. */
|
|
private void
|
|
IgnFi(
|
|
AD *pad,
|
|
FI far *pfi,
|
|
FS far *pfs)
|
|
{
|
|
/* Cached diff is meaningless if file isn't checked out */
|
|
DeleteCachedDiff(pad, pfi);
|
|
|
|
switch (pfs->fm)
|
|
{
|
|
default:
|
|
FatalError(szBadFileFormat, pad, pfi);
|
|
break;
|
|
|
|
case fmNonExistent:
|
|
case fmIn:
|
|
case fmAdd:
|
|
case fmDelIn:
|
|
case fmCopyIn:
|
|
case fmGhost:
|
|
Error("%&C/F is not checked out\n", pad, pfi);
|
|
break;
|
|
|
|
case fmDelOut:
|
|
SyncDel(pad, pfi, pfs);
|
|
break;
|
|
|
|
case fmOut:
|
|
pfs->fm = fmIn;
|
|
FreshCopy(pad, pfi);
|
|
DelBase(pad, pfi, pfs);
|
|
break;
|
|
|
|
case fmMerge:
|
|
case fmVerify:
|
|
case fmConflict:
|
|
Warn("restoring %&C/F to %&F@v%d (current is %&F@v%d)\n",
|
|
pad, pfi, pad, pfi, pfs->fv, pad, pfi, pfi->fv);
|
|
LocalBase(pad, pfi, pfs, fTrue);
|
|
pfs->fm = fmCopyIn;
|
|
DelBase(pad, pfi, pfs);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* checkin the marked files */
|
|
private F
|
|
FInMarked(
|
|
AD *pad,
|
|
F *pfAny)
|
|
{
|
|
register FI far *pfi;
|
|
FI far *pfiMac;
|
|
register FS far *pfs;
|
|
|
|
*pfAny = fFalse;
|
|
|
|
for (pfi=pad->rgfi, pfiMac=pfi+pad->psh->ifiMac; pfi < pfiMac; pfi++)
|
|
{
|
|
if (!pfi->fMarked)
|
|
continue;
|
|
|
|
AssertF(pfi->fk != fkVersion);
|
|
|
|
pfs = PfsForPfi(pad, pad->iedCur, pfi);
|
|
|
|
switch(pfs->fm)
|
|
{
|
|
default:
|
|
FatalError(szBadFileFormat, pad, pfi);
|
|
|
|
case fmGhost:
|
|
Error("%&C/F is ghosted\n", pad, pfi);
|
|
break;
|
|
|
|
case fmIn:
|
|
Error("%&C/F already checked in\n", pad, pfi);
|
|
break;
|
|
|
|
case fmOut:
|
|
*pfAny |= FInOutFile(pad, pfi, pfs);
|
|
break;
|
|
|
|
case fmNonExistent:
|
|
Error("%&C/F not checked in; the file does not (now) exist\n", pad, pfi);
|
|
break;
|
|
}
|
|
}
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/* Check in this file which is checked out. Return fTrue if the file was
|
|
* successfully checked in.
|
|
*/
|
|
private F
|
|
FInOutFile(
|
|
AD *pad,
|
|
FI far *pfi,
|
|
FS far *pfs)
|
|
{
|
|
IED ied;
|
|
IED iedMac = pad->psh->iedMac;
|
|
BI bi;
|
|
char szDiff[cchFileMax + 1];
|
|
char *szComment;
|
|
char szOwnersOut[cchUserMax*5]; /* big buffer; still check for full */
|
|
int cwOwnersOut = 0; /* how many others have it out too */
|
|
|
|
AssertF(pfi->fMarked && pfs->fm == fmOut);
|
|
strcpy(szOwnersOut, "");
|
|
|
|
if ((szComment = pad->szComment) == NULL &&
|
|
FCanQuery("no comment given for %&C/F\n", pad, pfi))
|
|
szComment = SzQuery("Comment for %&C/F: ", pad, pfi);
|
|
|
|
/* Create diff/checkpoint */
|
|
strcpy(szDiff, "");
|
|
|
|
/* SPAWN THE USER FILTER */
|
|
|
|
if (pad->flags&flagInFilters)
|
|
{
|
|
if (SpawnFilter(pfi->nmFile,pad->pthSRoot,szComment,
|
|
pad->nmProj, pad->pthSSubDir, (int)pfi->fk, pad->pthURoot) != 0)
|
|
{
|
|
PrErr(" warning: --> file %s excluded from checkin\n",
|
|
pfi->nmFile);
|
|
return (fFalse);
|
|
}
|
|
}
|
|
|
|
if ((pfi->fk == fkText || pfi->fk == fkUnicode)
|
|
&& !(pad->flags&flagInChecKpt))
|
|
{
|
|
/* if diff record has zero length (and user agreed), no history */
|
|
if (!FMkDae(pad, pfi, FMkDiff, pad->flags&(flagInDashB|flagInDashZ),
|
|
szDiff, szComment))
|
|
{
|
|
/* If update, nothing to do! */
|
|
if (!(pad->flags&flagInUpdate))
|
|
IgnFi(pad, pfi, pfs);
|
|
return fTrue;
|
|
}
|
|
}
|
|
|
|
else if ((pad->flags&flagInChecKpt) || pfi->fk == fkBinary)
|
|
FMkDae(pad, pfi, FMkCkptFile, /*fLocal*/fFalse, szDiff, szComment);
|
|
|
|
/* Remove possible reference to base file. */
|
|
DelBase(pad, pfi, pfs);
|
|
|
|
/* Update fs information. */
|
|
pfs->fv = ++pfi->fv;
|
|
pfs->fm = (pad->flags&flagInUpdate) ? fmOut : fmIn;
|
|
|
|
/* Change other user's modes to indicate they are now out of sync.
|
|
* Create a base file if any other users are in a checked out state.
|
|
*/
|
|
bi = biNil;
|
|
for (ied = 0; ied < iedMac; ied++)
|
|
{
|
|
if (ied == pad->iedCur)
|
|
continue;
|
|
|
|
pfs = PfsForPfi(pad, ied, pfi);
|
|
|
|
switch(pfs->fm)
|
|
{
|
|
default:
|
|
FatalError(szBadFileFormat, pad, pfi);
|
|
|
|
case fmIn:
|
|
pfs->fm = fmCopyIn;
|
|
break;
|
|
|
|
case fmOut:
|
|
case fmVerify:
|
|
case fmConflict:
|
|
/* keep track if others have file out */
|
|
cwOwnersOut++;
|
|
|
|
DelBase(pad, pfi, pfs);
|
|
if (bi == biNil)
|
|
{
|
|
bi = BiAlloc(pad);
|
|
MakeBase(pad, pfi, bi);
|
|
}
|
|
pfs->bi = bi;
|
|
pfs->fm = fmMerge;
|
|
break;
|
|
|
|
case fmNonExistent:
|
|
case fmDelIn:
|
|
case fmDelOut:
|
|
case fmGhost:
|
|
case fmAdd:
|
|
case fmCopyIn:
|
|
case fmMerge:
|
|
break;
|
|
}
|
|
}
|
|
|
|
InstallNewSrc(pad, pfi, !(pad->flags&flagInUpdate));
|
|
AppendLog(pad, pfi, szDiff, szComment);
|
|
|
|
/* print appropriate warning according to how many cwOwnersOut */
|
|
if ((pfi->fk == fkText || pfi->fk == fkUnicode) && cwOwnersOut > 0)
|
|
{
|
|
/* who else has it checked out */
|
|
FOutUsers(szOwnersOut, sizeof(szOwnersOut), pad, pfi);
|
|
|
|
if (cwOwnersOut == 1)
|
|
Warn("%&F is also checked out to %s who now needs to merge\n", pad, pfi, szOwnersOut);
|
|
else
|
|
Warn("%&F is also checked out to %s who now need to merge\n", pad, pfi, szOwnersOut);
|
|
}
|
|
|
|
return fTrue;
|
|
}
|