/* ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 1, or (at your option) ** any later version. ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Author : Alexandre Parenteau --- June 1998 */ /* * CvsIgnore.cpp --- parse the .cvsignore */ #include "stdafx.h" #include #include #include "FileTraversal.h" #include "AppConsole.h" #include "CvsIgnore.h" #include "getline.h" #include "fnmatch.h" #include "CvsPrefs.h" #ifndef WIN32 # include #endif /* !WIN32 */ #ifdef qMacCvsPP # include "MacCvsApp.h" # include "MacMisc.h" #endif /* qMacCvsPP */ #ifdef WIN32 # include "wincvs.h" # ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; # endif #endif /* WIN32 */ /* Parse a line of space-separated wildcards and add them to the list. */ /* mostly duplicated from cvs/src/ignore.c */ static void ign_add (char *ign, bool hold, std::vector & ignlist) { if (!ign || !*ign) return; int ign_hold = ignlist.size() == 0 ? -1 : (int)ignlist.size(); for (; *ign; ign++) { char *mark; char save; /* ignore whitespace before the token */ if (isspace (*ign)) continue; /* * if we find a single character !, we must re-set the ignore list * (saving it if necessary). We also catch * as a special case in a * global ignore file as an optimization */ if ((!*(ign+1) || isspace (*(ign+1))) && (*ign == '!' || *ign == '*')) { if (!hold) { /* permanently reset the ignore list */ ignlist.erase(ignlist.begin(), ignlist.end()); /* if we are doing a '!', continue; otherwise add the '*' */ if (*ign == '!') { continue; } } else if (*ign == '!') { /* temporarily reset the ignore list */ if (ign_hold >= 0) { ignlist.erase(ignlist.begin(), ignlist.begin() + ign_hold); ign_hold = -1; } continue; } } /* find the end of this token */ for (mark = ign; *mark && !isspace (*mark); mark++) /* do nothing */ ; save = *mark; *mark = '\0'; ignlist.push_back(CStr(ign)); *mark = save; if (save) ign = mark; else ign = mark - 1; } } // Read .cvsignore file and append entries to ignlist static bool ReadIgnoredFile(const char* fileName, std::vector & ignlist) { FILE *fp; char *line = NULL; size_t line_allocated = 0; fp = fopen(fileName, "r"); if(fp != 0L) { while (getline (&line, &line_allocated, fp) >= 0) ign_add (line, false, ignlist); if (ferror (fp)) cvs_err("Problem while parsing '%s'", fileName); fclose (fp); } if(line != 0L) free (line); return(fp != 0L); } void BuildIgnoredList(std::vector & ignlist, const char *path) { ignlist.erase(ignlist.begin(), ignlist.end()); static std::vector deflist; static bool deflistparsed = false; if(!deflistparsed) { #ifdef macintosh UFSSpec theFolder; CStr home; if(MacGetPrefsFolder(theFolder, home) == noErr) { #else /* !macintosh */ if(gCvsPrefs.Home() != 0L) { CStr home(gCvsPrefs.Home()); #endif /* !macintosh */ struct stat sb; if (stat(home, &sb) != 0 || !S_ISDIR(sb.st_mode)) { cvs_err("Warning : unable to access your HOME path '%s'\n", gCvsPrefs.Home()); cvs_err(" ~/.cvsignore will not be read\n"); } if(!home.empty() && !home.endsWith(kPathDelimiter)) home << kPathDelimiter; home << ".cvsignore"; // Read .cvsignore file from HOME directory. // If HOME dir doesn't have such a file then // try to read global file from executable path. if(ReadIgnoredFile(home, deflist) == false) { CStr appPath; #ifdef WIN32 ((CWincvsApp *)AfxGetApp())->GetAppPath(appPath); #elif defined(qUnix) // Unix version uses only .cvsignore file in HOME dir #else # ifdef qMacCvsPP appPath = CMacCvsApp::GetAppPath(); # endif /* qMacCvsPP */ #endif if(!appPath.empty()) { if(!appPath.endsWith(kPathDelimiter)) appPath << kPathDelimiter; appPath << ".cvsignore"; ReadIgnoredFile(appPath, deflist); } } } deflistparsed = true; } else ignlist = deflist; #if qUnix // from cvs/src/ignore.c CStr ign_default(". .. core RCSLOG tags TAGS RCS SCCS .make.state\ .nse_depinfo #* .#* cvslog.* ,* CVS CVS.adm .del-* *.a *.olb *.o *.obj\ *.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej *.exe _$* *$"); ign_add (ign_default, false, ignlist); #endif UStr ignPath(path); if(!ignPath.endsWith(kPathDelimiter)) ignPath << kPathDelimiter; ignPath << ".cvsignore"; // load the file from the current source directory ReadIgnoredFile(ignPath, ignlist); } bool MatchIgnoredList(const char * filename, const std::vector & ignlist) { std::vector::const_iterator i; for(i = ignlist.begin(); i != ignlist.end(); ++i) { if(fnmatch (*i, filename, 0) == 0) return true; } return false; }