BOOL MRE::FPushFile ( PMREFile * ppmrefile, SZC szFile, HANDLE hFile ) { _TCHAR szCanon[ ctchMrePathMax ]; NI ni; PFI pfi = NULL; precondition ( szFile ); ni = NiFromName ( SzFullCanonFilename ( szFile, szCanon, countof(szCanon) ) ); m_pmrefRoot->Push ( ni ); m_mrelog.LogPush ( ni ); if ( FFileInfoFromNi ( ni, &pfi ) ) { assert ( pfi->fiTime != 0 ); assert ( pfi->fiSize != 0 ); pfi->SetBuildId ( BuildId() ); } else { // insert a new FILEINFO FI fi(ni, fsmVisited, BuildId()); // add in the new one after updating the timestamp info if ( !FInsertFileInfo ( fi ) ) { // review:error } else { FFileInfoFromNi ( ni, &pfi ); if ( pfi ) { if ( hFile != INVALID_HANDLE_VALUE ) { ::FFileInfo ( hFile, *pfi ); CheckIgnoreFile ( *pfi, hFile ); } else { ::FFileInfo ( szCanon, *pfi ); } } } } // have we visited this file recently? if ( pfi ) { if ( FUpdateFileInfo ( pfi, hFile ) ) { // clear out any status bits that may change how we operate with // this file in the future pfi->ClearFstatus ( fsmInclByPch ); } } if ( !(pfi && pfi->FIsFsmSet ( fsmIgnoreDep )) ) { m_mrfibufRoot.FAddFileDep ( ni ); } *ppmrefile = m_pmrefRoot; return fTrue; }
plString plProduct::ProductString() { static plString _cache = plString::Format( "%s.%u.%u - " RELEASE_ACCESS "." RELEASE_TYPE, CoreName().c_str(), BranchId(), BuildId()); return _cache; }
BOOL MRE::FUpdateTargetFile ( SZC szTarget, TrgType trgtype ) { // REVIEW:TODO actually do the patch (novel concept) _TCHAR szCanon [ ctchMrePathMax ]; NI ni; PFI pfi; BOOL fRet = fFalse; ni = NiFromName ( SzFullCanonFilename ( szTarget, szCanon, countof(szCanon) ) ); if ( trgtype == trgtypeObject && FFileInfoFromNi ( ni, &pfi ) ) { MREFT mreft; QWORD cb; switch ( m_lcrechandler.LcrhrPatchFile ( pfi->BuildId(), szCanon ) ) { case LCRecHandler::lcrhrFail : case LCRecHandler::lcrhrNotApplicable : { _tutime ( szCanon, NULL); break; } case LCRecHandler::lcrhrSuccess : { break; } default : { notReached(); } } IncBuildId(); // update our FILEINFO so that we don't have to deal with those // changes on our next refresh. if ( ::FFileInfo ( szCanon, mreft, cb ) ) { pfi->fiTime = mreft; pfi->fiSize = cb; pfi->SetBuildId ( BuildId() ); } fRet = fTrue; } else { fRet = !_tutime ( szCanon, NULL); } m_mrelog.LogNote ( "Note: update of '%s', type = %d, was %ssuccessful.\n", szCanon, int(trgtype), fRet ? "" : "un" ); return fRet; }
//----------------------------------------------------------------------------- // MRE::YnmFileOutOfDate // // Purpose: tells whether a file is, isn't, or may be out of date // // Input: a SRCTARG containing the following fields: // st.szFileSrc, source file // st.szFileTarg, target (object) file // st.szOptions, compiler options it will be built with this time // // Output: // st.dwWeightMaybe, weighting factor for when we return ynmMaybe // // Returns: // ynmNo, ynmYes, or ynmMaybe // // Note: // This method depends on having up-to-date information from // FRefreshFilesysInfo //----------------------------------------------------------------------------- YNM MRE::YnmFileOutOfDate ( SRCTARG & st ) { precondition ( st.szSrc ); precondition ( st.szTarg ); YNM ynmRet = ynmYes; _TCHAR szCanonSrc [ ctchMrePathMax ]; _TCHAR szCanonTarg[ ctchMrePathMax ]; NI niSrc; NI niTarg; NI niOptions; BOOL fUsingPch = fFalse; st.dwWeightMaybe = 0; niSrc = NiFromName ( SzFullCanonFilename ( st.szSrc, szCanonSrc, countof(szCanonSrc) ) ); niTarg = NiFromName ( SzFullCanonFilename ( st.szTarg, szCanonTarg, countof(szCanonTarg) ) ); niOptions = st.szOptions ? NiFromName ( st.szOptions ) : niNil; // find out if it is using a pch...we can safely skip checking files // that were included in the pch in our dep scan. if ( st.szOptions ) { SZC szYu = NULL; SZC szT = st.szOptions; // find last " -Yu" in the options. this will skip any in the -D... // portions and won't match any path name in the includes // since the driver canonicalizes by lowercasing them. while ( szT = _tcsstr ( szT, _TEXT(" -Yu") ) ) { szYu = szT; szT++; } // now, make sure we are not also creating a new pch via a 2-level // pch create (both -Yc and -Yu on the command line) szT = st.szOptions; SZC szYc = NULL; while ( szT = _tcsstr ( szT, _TEXT(" -Yc") ) ) { szYc = szT; szT++; } // check to see if are using and not creating a PCH. fUsingPch = ((szYu != NULL) && (szYc == NULL)); } PFI pfiSrc = NULL; if ( FFileInfoFromNi ( niSrc, &pfiSrc ) ) { if ( !st.fCpp ) { // not a C++ file anymore, so remove any info we have and bail m_mpnifi.remove ( niSrc ); m_mpnifi.remove ( niTarg ); return ynmYes; } assert ( pfiSrc->niFile == niSrc ); assert ( pfiSrc->FHasTarget() ); // pre-check the source/target pair to see if they are out of date // in any way. This call will update the outofdate bit if anything // changed (options, missing src/targ file, src/targ file changes). CheckSrcTarg ( pfiSrc, niTarg, niOptions ); // if the file is not already marked as out of date, or out of date // due to rude file changes or class deps, then we have to do some // more work. if ( !pfiSrc->FTargOutOfDate() && !FIsFileOutOfDate ( pfiSrc ) ) { BldId bldidSrc = pfiSrc->BuildId(); unsigned itagni = 0; // go thru the loop at least once // 1st iteration checks for any existing pending files that would // cause us to classify this as a maybe instead of a no. // 2nd iteration will happen if a new changed file we haven't // visited yet is included by this source file. for ( unsigned cIterations = 0; cIterations < 2; cIterations++ ) { if ( !FLoadMrfi ( pfiSrc->Ni() ) ) { break; } // does the file include any of the "pending // parse" files? unsigned itagniMac = m_rgtagniPending.size(); for ( ; itagni < itagniMac; itagni++ ) { TagNi * ptni = &m_rgtagniPending[ itagni ]; debug ( SZC sz = SzFromNi ( ptni->Ni() ) ); if ( ptni->BuildId() > bldidSrc && FNiDependsOnNiFile ( pfiSrc->Ni(), ptni->Ni() ) ) { ynmRet = ynmMaybe; st.dwWeightMaybe += 1 + m_mrfibufRoot.MapNiClassdep().count(); m_mrelog.LogNote ( "Note: '%s' may be out of date due to changes in '%s'.\n", szCanonSrc, SzFromNi ( ptni->Ni() ) ); } else if ( m_mrelog.FLogging() ) { m_mrelog.LogNote ( "Note: '%s' not out of date due to '%s' or " "build id's (%d,%d).\n", szCanonSrc, SzFromNi ( ptni->Ni() ), bldidSrc, ptni->BuildId() ); } } // if we didn't find any files that need to be compiled, // we check for any new files that have changed, and check // again, else we are done. if ( st.dwWeightMaybe == 0 && !FCheckVisitedDeps ( pfiSrc, fUsingPch ) ) { ynmRet = ynmNo; break; } } if ( ynmRet == ynmNo ) { m_mrelog.LogNote ( "Note: '%s' is not out of date due to current pending changes.\n", szCanonSrc ); } } } else { // file didn't exist in our list. this is our only chance to snarf // the compile options. FI fiSrc(niSrc, fsmHasTarget | fsmOutOfDate, BuildId(), niOptions); FI fiTrg(niTarg, fsmIsTarget | fsmOutOfDate); // add the file into the list if it exists. if ( ::FFileInfo ( szCanonSrc, fiSrc ) ) { ::FFileInfo ( szCanonTarg, fiTrg ); FInsertFileInfo ( fiSrc ); FInsertFileInfo ( fiTrg ); FFileInfoFromNi ( niSrc, &pfiSrc ); } } if ( pfiSrc && pfiSrc->NiOptions() != niOptions ) { assert ( ynmRet == ynmYes ); if ( m_mrelog.FLogging() && pfiSrc->NiOptions() != niNil ) { m_mrelog.LogNote ( "Note: '%s' must be compiled date due to options changing.\n", SzFromNi ( pfiSrc->Ni() ) ); } pfiSrc->SetNiOptions ( niOptions ); } if ( m_mrelog.FLogging() ) { m_mrelog.LogNote ( "Note: '%s' returning %s\n", szCanonSrc, ((ynmRet == ynmNo) ? "ynmNo" : ((ynmRet == ynmYes) ? "ynmYes" : "ynmMaybe")) ); } return ynmRet; }
BOOL MRE::FCloseCompiland ( PMREFile pmrefile, BOOL fCommit ) { assert ( m_pmrefRoot ); assert ( pmrefile == m_pmrefRoot ); _TCHAR szStreamName[ ctchMrePathMax ]; Stream * pstream; BOOL fRet = fFalse; if ( m_mrelog.FLogging() ) { m_mrelog.LogNote ( "Note: '%s' deps will %sbe committed.\n", SzFromNi ( m_pmrefRoot->Ni() ), fCommit ? "" : "not " ); m_mrelog.LogSep(); } if ( fCommit ) { _sntprintf ( szStreamName, countof(szStreamName), c_szMreFileFmt, m_pmrefRoot->Ni() ); // if we haven't hit all the classes that were noted as mr detectable, // we need to rude out those classes. Array<NI> & rgni = m_pmrefRoot->RgNiClassesChanged(); unsigned iniMax = rgni.size(); for ( unsigned ini = 0; ini < iniMax; ini++ ) { if ( rgni[ ini ] != niNil ) { // a class we didn't see a different type id for... PCI pci; if ( FClassInfoFromNi ( rgni[ ini ], &pci ) ) { // we have to promote all nested types to rude. NoteRudeNestedClasses ( pci->Ti() ); } } } if ( m_ppdb->OpenStream ( szStreamName, &pstream ) ) { // if we need to merge the class dependency data, we need // to read in the old stream first... if ( !m_pmrefRoot->FAllCodeCompiled() ) { MRFIBuf mrfibufT; mrfibufT.SetPmre ( this ); if ( mrfibufT.FInitFromStream ( pstream ) ) { assert ( mrfibufT.Pmrfi()->niFile == m_pmrefRoot->Ni() ); m_mrfibufRoot.FmergeClassDeps ( mrfibufT ); } } if ( m_mrfibufRoot.FReplaceStream ( pstream ) ) { fRet = fTrue; } else { pstream->Delete(); } pstream->Release(); } if ( fRet ) { // if everything is ok for the gen'ed dependencies, we // need to update the build # in the file info stream PFI pfi = NULL; verify ( m_mpnifi.map ( m_pmrefRoot->Ni(), &pfi ) ); if ( pfi ) { pfi->SetBuildId ( BuildId() ); verify ( m_mpnifi.map ( pfi->NiRelated(), &pfi ) ); if ( pfi ) { pfi->SetBuildId ( BuildId() ); } } } } else { fRet = fTrue; } delete m_pmrefRoot; m_pmrefRoot = NULL; return fRet; }
BOOL MRE::FOpenCompiland ( PMREFile * ppmrefile, SZC szFileSrc, SZC szFileTarg ) { BOOL fRet = fFalse; _TCHAR szCanonSrc [ ctchMrePathMax ]; _TCHAR szCanonTarg[ ctchMrePathMax ]; *ppmrefile = NULL; // update the build count in the fileinfo stream IncBuildId(); if ( m_mrfibufRoot.FInitEmpty() ) { NI niSrc, niTarg; niSrc = NiFromName ( SzFullCanonFilename ( szFileSrc, szCanonSrc, countof(szCanonSrc) ) ); niTarg = NiFromName ( SzFullCanonFilename ( szFileTarg, szCanonTarg, countof(szCanonTarg) ) ); m_mrelog.LogCompiland ( niSrc, niTarg ); if ( niSrc != niNil && niTarg != niNil ) { m_mrfibufRoot.SetNiFile ( niSrc, niTarg ); // insert/update the fileinfo's if necessary. PFI pfiSrc = NULL; if ( FFileInfoFromNi ( niSrc, &pfiSrc ) ) { assert ( pfiSrc->FHasTarget() ); pfiSrc->SetFstatus ( fsmOutOfDate ); m_mrelog.LogCompilandOptions ( pfiSrc->NiOptions() ); } else { FI fiSrc(niSrc, fsmHasTarget | fsmOutOfDate, BuildId()); verify ( ::FFileInfo ( szCanonSrc, fiSrc ) ); FInsertFileInfo ( fiSrc ); } PFI pfiTarg = NULL; if ( !FFileInfoFromNi ( niTarg, &pfiTarg ) ) { FI fiTarg(niTarg, fsmIsTarget); ::FFileInfo ( szCanonTarg, fiTarg ); FInsertFileInfo ( fiTarg ); } // update xref data, must get the pointers now, after all inserts if ( FFileInfoFromNi ( niSrc, &pfiSrc ) ) { pfiSrc->SetNiRelated ( niTarg ); } if ( FFileInfoFromNi ( niTarg, &pfiTarg ) ) { pfiTarg->SetNiRelated ( niSrc ); } if ( pfiSrc && pfiTarg && (m_pmrefRoot = new MREF(this, niSrc)) ) { // ready to go! *ppmrefile = m_pmrefRoot; fRet = fTrue; } } } return fRet; }