OSDN Git Service

PATCH: [ 766287 ] Use our own dir traversal (instead of diff's)
authorPerry Rapp <elsapo@users.sourceforge.net>
Thu, 24 Jul 2003 12:53:41 +0000 (12:53 +0000)
committerPerry Rapp <elsapo@users.sourceforge.net>
Thu, 24 Jul 2003 12:53:41 +0000 (12:53 +0000)
Src/Diff.cpp
Src/DiffContext.h
Src/DiffThread.cpp
Src/DirDoc.cpp
Src/Merge.dsp
Src/readme.txt

index 80dcb5c..00cf967 100644 (file)
@@ -31,8 +31,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "getopt.h"
 #include "fnmatch.h"
 #include "io.h"
-#include "DirDoc.h"
-#include "logfile.h"
 
 // reduce some noise produced with the MSVC compiler
 #if defined (_AFXDLL)
@@ -40,8 +38,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #endif
 
 
-extern int diff_dirs (CDiffContext*, int);
-
 
 #ifndef DEFAULT_WIDTH
 #define DEFAULT_WIDTH 130
@@ -52,497 +48,74 @@ extern int diff_dirs (CDiffContext*, int);
 #endif
 
 
-extern CLogFile gLog;
-
-int compare_files (LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR, CDiffContext*, int);
-int excluded_filename (char const *f);
 
 /* Nonzero for -r: if comparing two directories,
    compare their common subdirectories recursively.  */
 
 int recursive;
 
-/* For debugging: don't do discard_confusing_lines.  */
-
-static char const **exclude;
-static int exclude_alloc, exclude_count;
-
-int
-excluded_filename (char const *f)
-{
-  int i;
-  for (i = 0;  i < exclude_count;  i++)
-    if (fnmatch (exclude[i], f, 0) == 0)
-      return 1;
-  return 0;
-}
-
-static char const *
-filetype (struct stat const *st)
-{
-  /* See Posix.2 section 4.17.6.1.1 and Table 5-1 for these formats.
-     To keep diagnostics grammatical, the returned string must start
-     with a consonant.  */
-
-  if (S_ISREG (st->st_mode))
-    {
-      if (st->st_size == 0)
-       return "regular empty file";
-      /* Posix.2 section 5.14.2 seems to suggest that we must read the file
-        and guess whether it's C, Fortran, etc., but this is somewhat useless
-        and doesn't reflect historical practice.  We're allowed to guess
-        wrong, so we don't bother to read the file.  */
-      return "regular file";
-    }
-  if (S_ISDIR (st->st_mode)) return "directory";
-
-  /* other Posix.1 file types */
-#ifdef S_ISBLK
-  if (S_ISBLK (st->st_mode)) return "block special file";
-#endif
-#ifdef S_ISCHR
-  if (S_ISCHR (st->st_mode)) return "character special file";
-#endif
-#ifdef S_ISFIFO
-  if (S_ISFIFO (st->st_mode)) return "fifo";
-#endif
-
-  /* other popular file types */
-  /* S_ISLNK is impossible with `stat'.  */
-#ifdef S_ISSOCK
-  if (S_ISSOCK (st->st_mode)) return "socket";
-#endif
-
-  return "weird file";
-}
-
-
-
-int FileIsBinary(int fd)
-{
-       int bResult=0;
-       int cnt;
-       char buf[128];
-       long prevpos = tell(fd);
-
-       // check front of file first
-       lseek(fd, 0L, SEEK_SET);
-       cnt=read(fd, buf, sizeof buf);
-       if (cnt>0)
-       {
-               for (register int i=0; i < cnt; i++)
-               {
-                       if (((unsigned char)buf[i]) < 0x09)
-                       {
-                               bResult=1;
-                               break;
-                       }
-               }
-    }
-
-       if (!bResult)
-       {
-               // no binary chars found, look at end of file
-               lseek(fd, -cnt, SEEK_END);
-               cnt=read(fd, buf, cnt);
-               if (cnt>0)
-               {
-                       for (register int i=0; i < cnt; i++)
-                       {
-                               if (((unsigned char)buf[i]) < 0x09)
-                               {
-                                       bResult=1;
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       lseek(fd, prevpos, SEEK_SET);
-       return bResult;
-}
 
-/*
-  Check a file or directory against the context file/directory filter
-  precondition: pCtx is non-null
-*/
-static bool
-DoesPassFilter(CDiffContext *pCtx, int dir_p, LPCTSTR name)
-{
-  return dir_p ? !!pCtx->m_piFilter->includeDir(name) 
-         : !!pCtx->m_piFilter->includeFile(name);
-}
-
-/* Compare two files (or dirs) with specified names
-   DIR0/NAME0 and DIR1/NAME1, at level DEPTH in directory recursion.
-   (if DIR0 is 0, then the name is just NAME0, etc.)
+/* Compare two specified files
    This is self-contained; it opens the files and closes them.
 
    Value is 0 if files are the same, 1 if different,
    2 if there is a problem opening them.  */
 
 int
-compare_files (LPCTSTR dir0, LPCTSTR name0, 
-              LPCTSTR dir1, LPCTSTR name1, 
-              CDiffContext *pCtx, int depth)
+just_compare_files (LPCTSTR filepath1, LPCTSTR filepath2, int depth)
 {
-  struct file_data inf[2];
-  register int i;
-  int val=0;
-  int same_files;
-  int failed = 0;
-  LPTSTR free0 = 0, free1 = 0;
-  bool lunique=false,runique=false;
-
-  memset(&inf[0], 0, sizeof(struct file_data));
-  memset(&inf[1], 0, sizeof(struct file_data));
-
-  /* If this is directory comparison, perhaps we have a file
-     that exists only in one of the directories.  */
-
-  gLog.Write(_T("Comparing: n0=%s, n1=%s, d0=%s, d1=%s"), name0, name1, dir0, dir1);
-
-  if (! ((name0 != 0 && name1 != 0)
-        || (unidirectional_new_file_flag && name1 != 0)
-        || entire_new_file_flag))
-    {
-         // flag the unique status for later processing
-         lunique=(name0 != 0);
-         runique=(name0 == 0);
-    }
-
-  /* Mark any nonexistent file with -1 in the desc field.  */
-  /* Mark unopened files (e.g. directories) with -2. */
+       struct file_data inf[2];
 
-  inf[0].desc = (name0 == 0 ? -1 : -2);
-  inf[1].desc = (name1 == 0 ? -1 : -2);
+       ZeroMemory(&inf[0], sizeof(inf[0]));
+       ZeroMemory(&inf[1], sizeof(inf[1]));
 
-  /* Now record the full name of each file, including nonexistent ones.  */
+       inf[0].name = filepath1;
+       inf[1].name = filepath2;
 
-  if (name0 == 0)
-    name0 = name1;
-  if (name1 == 0)
-    name1 = name0;
-
-  inf[0].name = dir0 == 0 ? name0 : (free0 = dir_file_pathname (dir0, name0));
-  inf[1].name = dir1 == 0 ? name1 : (free1 = dir_file_pathname (dir1, name1));
-
-  /* Stat the files.  Record whether they are directories.  */
-
-  for (i = 0; i <= 1; i++)
-    {
-      bzero (&inf[i].stat, sizeof (struct stat));
-      inf[i].dir_p = 0;
-
-      if (inf[i].desc != -1)
+       inf[0].desc = open(inf[0].name, O_RDONLY|O_BINARY, 0);
+       if (inf[0].desc < 0)
        {
-         int stat_result;
-
-         if (i && stricmp (inf[i].name, inf[0].name) == 0)
-           {
-             inf[i].stat = inf[0].stat;
-             stat_result = 0;
-           }
-         else if (strcmp (inf[i].name, "-") == 0)
-           {
-             inf[i].desc = STDIN_FILENO;
-             stat_result = fstat (STDIN_FILENO, &inf[i].stat);
-             if (stat_result == 0 && S_ISREG (inf[i].stat.st_mode))
-               {
-                 off_t pos = lseek (STDIN_FILENO, (off_t) 0, SEEK_CUR);
-                 if (pos == -1)
-                   stat_result = -1;
-                 else
-                   {
-                     if (pos <= inf[i].stat.st_size)
-                       inf[i].stat.st_size -= pos;
-                     else
-                       inf[i].stat.st_size = 0;
-                     /* Posix.2 4.17.6.1.4 requires current time for stdin.  */
-                     time (&inf[i].stat.st_mtime);
-                   }
-               }
-           }
-         else
-           stat_result = stat (inf[i].name, &inf[i].stat);
-
-         if (stat_result != 0)
-           {
-             perror_with_name (inf[i].name);
-             failed = 1;
-           }
-         else
-           {
-             inf[i].dir_p = S_ISDIR (inf[i].stat.st_mode) && inf[i].desc != 0;
-             if (inf[1 - i].desc == -1)
-               {
-                 inf[1 - i].dir_p = inf[i].dir_p;
-                 inf[1 - i].stat.st_mode = inf[i].stat.st_mode;
-               }
-           }
+               return 2;
        }
-    }
-
-  if (pCtx->m_piFilter)
-  {
-    if (!DoesPassFilter(pCtx, inf[0].dir_p, inf[0].name)) 
-    {
-       val = 88;
-       goto compare_files_end;
-    }
-    if (!DoesPassFilter(pCtx, inf[1].dir_p, inf[1].name))
-    {
-       val = 88;
-       goto compare_files_end;
-    }
-  }
-
-  // delayed unique determination so we can see if file is a directory or not
-  if (!failed && (lunique || runique))
-  {
-         BYTE code=0;
-      LPCTSTR name=0;
-         if (lunique)
-         {
-                 if (inf[0].dir_p != 0)
-                         code = FILE_LDIRUNIQUE;
-                 else
-                         code = FILE_LUNIQUE;
-                 name = name0;
-         }
-         else
-         {
-                 if (inf[1].dir_p != 0)
-                         code = FILE_RDIRUNIQUE;
-                 else
-                         code = FILE_RUNIQUE;
-                 name = name1;
-         }
-         pCtx->AddDiff(name, dir0, dir1, inf[0].stat.st_mtime, inf[1].stat.st_mtime, code);
-      gLog.Write(_T("\tUnique\r\n"));
-         if (free0)
-                 free (free0);
-         if (free1)
-                 free (free1);
-      return 1;
-  }
-
-  if (! failed && depth == 0 && inf[0].dir_p != inf[1].dir_p)
-    {
-      /* If one is a directory, and it was specified in the command line,
-        use the file in that dir with the other file's basename.  */
-
-      int fnm_arg = inf[0].dir_p;
-      int dir_arg = 1 - fnm_arg;
-      char const *fnm = inf[fnm_arg].name;
-      char const *dir = inf[dir_arg].name;
-      char const *p = strrchr (fnm, '/');
-      char const *filename = inf[dir_arg].name
-       = dir_file_pathname (dir, p ? p + 1 : fnm);
-
-      if (strcmp (fnm, "-") == 0)
-       fatal ("can't compare - to a directory");
-
-      if (stat (filename, &inf[dir_arg].stat) != 0)
+       inf[1].desc = open(inf[1].name, O_RDONLY|O_BINARY, 0);
+       if (inf[1].desc < 0)
        {
-         perror_with_name (filename);
-         failed = 1;
+               close(inf[0].desc);
+               return 2;
        }
-      else
-       inf[dir_arg].dir_p = S_ISDIR (inf[dir_arg].stat.st_mode);
-    }
-
-  if (failed)
-    {
 
-      /* If either file should exist but does not, return 2.  */
+       int diff_flag=0;
 
-      val = 2;
-      pCtx->AddDiff(name0, dir0, dir1, 0, 0, FILE_ERROR);
-    }
-#if defined(__MSDOS__) || defined(__NT__) || defined(WIN32)
-  else if (same_files = 0) /* yes, only ONE equal sign intended! hmo11apr93 */
-    ;
-#else
-  else if ((same_files =    inf[0].stat.st_ino == inf[1].stat.st_ino
-                        && inf[0].stat.st_dev == inf[1].stat.st_dev
-                        && inf[0].stat.st_size == inf[1].stat.st_size
-                        && inf[0].desc != -1
-                        && inf[1].desc != -1)
-          && no_diff_means_no_output)
-    {
-      /* The two named files are actually the same physical file.
-        We know they are identical without actually reading them.  */
+       // Do the actual comparison (generating a change script)
+       int val = 0;
+       struct change *script = diff_2_files (inf, depth, &diff_flag);
 
-      val = 0;
-      pCtx->AddDiff(name0, dir0, dir0, inf[0].stat.st_mtime, inf[1].stat.st_mtime, FILE_SAME);
-    }
-#endif /*__MSDOS__||__NT__*/
-  else if (inf[0].dir_p & inf[1].dir_p)
-    {
-      if (output_style == OUTPUT_IFDEF)
-       fatal ("-D option not supported with directories");
-
-      /* If both are directories, compare the files in them.  */
-
-      if (depth > 0 && !recursive)
-       {
-         /* But don't compare dir contents one level down
-            unless -r was specified.  */
-         message ("Common subdirectories: %s and %s\n",
-                  inf[0].name, inf[1].name);
-         val = 0;
-       }
-      else
+       // Free change script (which we don't want)
+       if (script != NULL)
        {
-         gLog.Write(_T("\tDirs found.\r\n"));
-
-         CDiffContext ctx(inf[0].name, inf[1].name, *pCtx);
-         val = diff_dirs (&ctx, depth);
+               struct change *p,*e;
+               for (e = script; e; e = p)
+               {
+                       p = e->link;
+                       free (e);
+               }
+               val = 1; /* different */
        }
 
-    }
-  else if ((inf[0].dir_p | inf[1].dir_p)
-          || (depth > 0
-              && (! S_ISREG (inf[0].stat.st_mode)
-                  || ! S_ISREG (inf[1].stat.st_mode))))
-    {
-      /* Perhaps we have a subdirectory that exists only in one directory.
-        If so, just print a message to that effect.  */
+       // Tell diff code to cleanup
+       cleanup_file_buffers(inf);
 
-      if (inf[0].desc == -1 || inf[1].desc == -1)
+       // close open file handles
+       if (close(inf[0].desc) != 0)
        {
-         if ((inf[0].dir_p | inf[1].dir_p)
-             && recursive
-             && (entire_new_file_flag
-                 || (unidirectional_new_file_flag && inf[0].desc == -1)))
-         {
-                 gLog.Write(_T("\tDirs found.\r\n"));
-                 CDiffContext ctx(inf[0].name, inf[1].name, *pCtx);
-                 val = diff_dirs (&ctx, depth);
-         }
-         else
-           {
-             char const *dir = (inf[0].desc == -1) ? dir1 : dir0;
-             /* See Posix.2 section 4.17.6.1.1 for this format.  */
-             message ("Only in %s: %s\n", dir, name0);
-             val = 1;
-           }
+               val = 2;
        }
-      else
+       if (close(inf[1].desc) != 0)
        {
-         /* We have two files that are not to be compared.  */
-
-         /* See Posix.2 section 4.17.6.1.1 for this format.  */
-         message5 ("File %s is a %s while file %s is a %s\n",
-                   inf[0].name, filetype (&inf[0].stat),
-                   inf[1].name, filetype (&inf[1].stat));
-
-         /* This is a difference.  */
-         val = 1;
-         pCtx->AddDiff(name0, dir0, dir1, inf[0].stat.st_mtime, inf[1].stat.st_mtime, FILE_DIFF);
-       }
-    }
-  else if ((no_details_flag & ~ignore_some_changes)
-          && inf[0].stat.st_size != inf[1].stat.st_size
-          && (inf[0].desc == -1 || S_ISREG (inf[0].stat.st_mode))
-          && (inf[1].desc == -1 || S_ISREG (inf[1].stat.st_mode)))
-    {
-      message ("Files %s and %s differ\n", inf[0].name, inf[1].name);
-      val = 1;
-      pCtx->AddDiff(name0, dir0, dir1, inf[0].stat.st_mtime, inf[1].stat.st_mtime, FILE_DIFF);
-    }
-  else
-    {
-      /* Both exist and neither is a directory.  */
-      int o_binary = always_text_flag ? O_BINARY : 0;
-      o_binary = O_BINARY; // Perry 2002-12-08 CTRL-Z screws things up in text mode 
-         if (!ignore_eol_diff) o_binary = O_BINARY;
-      /* Open the files and record their descriptors.  */
-
-      if (inf[0].desc == -2)
-       if ((inf[0].desc = open (inf[0].name, O_RDONLY|o_binary, 0)) < 0)
-         {
-           perror_with_name (inf[0].name);
-           failed = 1;
-         }
-      if (inf[1].desc == -2)
-       if (same_files)
-         inf[1].desc = inf[0].desc;
-       else if ((inf[1].desc = open (inf[1].name, O_RDONLY|o_binary, 0)) < 0)
-         {
-           perror_with_name (inf[1].name);
-           failed = 1;
+               val = 2;
        }
 
-       if (!same_files && inf[0].desc>0 && inf[1].desc>0)
-       {
-               /* Actually compare files */
-               struct change *script=NULL;
-               int bin_status=0; /* 1 = bin+same, -1 = bin+different */
-               script = diff_2_files (inf, depth, &bin_status);
-               if (script != NULL)
-               {
-                       struct change *p,*e;
-                       for (e = script; e; e = p)
-                       {
-                               p = e->link;
-                               free (e);
-                       }
-                       val = 1; /* different */
-               }
-               cleanup_file_buffers(inf);
-
-               // close open file handles & record error if problem closing
-               if (inf[0].desc >= 0 && close (inf[0].desc) != 0)
-               {
-                       perror_with_name (inf[0].name);
-                       val = 2;
-               }
-               if (inf[1].desc >= 0 && inf[0].desc != inf[1].desc && close (inf[1].desc) != 0)
-               {
-                       perror_with_name (inf[1].name);
-                       val = 2;
-               }
-
-               if (val==2)
-               {
-                       pCtx->AddDiff(name0, dir0, dir1, inf[0].stat.st_mtime, inf[1].stat.st_mtime, FILE_ERROR);
-                       gLog.Write(_T("\t%s.\r\n"), val==2? "error":"different");
-               }
-               else if (bin_status)
-               {
-                       if (bin_status == 1)
-                       {
-                               pCtx->AddDiff(name0, dir0, dir1, inf[0].stat.st_mtime, inf[1].stat.st_mtime, FILE_BINSAME);
-                               gLog.Write(_T("\tsame binary.\r\n"));
-                       }
-                       else
-                       {
-                               pCtx->AddDiff(name0, dir0, dir1, inf[0].stat.st_mtime, inf[1].stat.st_mtime, FILE_BINDIFF);
-                               gLog.Write(_T("\tdifferent binary.\r\n"));
-                       }
-               }
-               else if (val==1)
-               {
-                       pCtx->AddDiff(name0, dir0, dir1, inf[0].stat.st_mtime, inf[1].stat.st_mtime, FILE_DIFF);
-                       gLog.Write(_T("\tdifferent.\r\n"));
-               }
-               else if (val==0)
-               {
-                       pCtx->AddDiff(name0, dir0, dir1, inf[0].stat.st_mtime, inf[1].stat.st_mtime, FILE_SAME);
-                       gLog.Write(_T("\tidentical.\r\n"));
-               }
-       }
-    }
-
-compare_files_end:
-
-  if (free0)
-    free (free0);
-  if (free1)
-    free (free1);
+       return val;
+}
 
 
-  return val;
-}
index c38f60a..1aa4c6e 100644 (file)
@@ -27,6 +27,8 @@ struct dirdata
 #define FILE_BINDIFF     6
 #define FILE_LDIRUNIQUE  7
 #define FILE_RDIRUNIQUE  8
+#define FILE_SKIP        9
+#define FILE_DIRSKIP    10
 
 struct DIFFITEM
 {
index fcac6cc..eb22f54 100644 (file)
@@ -2,11 +2,11 @@
 #include "diffcontext.h"
 #include "diffthread.h"
 #include "diff.h"
+#include "DirScan.h"
 
 // Static structure for sharing data with thread
 static DiffFuncStruct diffParam;
 
-int compare_files (LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR, CDiffContext*, int);
 
 CDiffThread::CDiffThread()
 {
@@ -27,6 +27,8 @@ CDiffContext * CDiffThread::SetContext(CDiffContext * pCtx)
        return pTempContext;
 }
 
+// Launch worker thread
+// called on main thread
 UINT CDiffThread::CompareDirectories(CString dir1, CString dir2)
 {
        diffParam.path1 = dir1;
@@ -56,16 +58,18 @@ UINT CDiffThread::GetThreadState()
        return diffParam.nThreadState;
 }
 
+// called on worker thread
 UINT DiffThread(LPVOID lpParam)
 {
        DiffFuncStruct *myStruct = (DiffFuncStruct *) lpParam;
        HWND hWnd = myStruct->hWindow;
        UINT msgID = myStruct->msgUIUpdate;
 
-       compare_files (0, (char const *)(LPCTSTR)myStruct->path1, 
-                              0, (char const *)(LPCTSTR)myStruct->path2,
-                                  myStruct->context, 0);
-
+       bool casesensitive = false;
+       int depth = -1;
+       CString subdir; // blank to start at roots specified in diff context
+       DirScan(subdir, myStruct->context, casesensitive, depth);
+       
        // Send message to UI to update
        diffParam.nThreadState = THREAD_COMPLETED;
        SendMessage(hWnd, msgID, NULL, NULL);
index 5982238..2a3aa4a 100644 (file)
@@ -203,6 +203,7 @@ diff_dirs2 (filevec, handle_file, depth)
   return val;
 }*/
 
+// Perform directory comparison again from scratch
 void CDirDoc::Rescan()
 {
        if (!m_pCtxt) return;
index a1a3915..1145532 100644 (file)
@@ -196,10 +196,6 @@ SOURCE=.\DiffThread.cpp
 # End Source File
 # Begin Source File
 
-SOURCE=.\Dir.cpp
-# End Source File
-# Begin Source File
-
 SOURCE=.\DirActions.cpp
 # End Source File
 # Begin Source File
@@ -246,6 +242,10 @@ SOURCE=.\DirFrame.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\DirScan.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\DirView.cpp
 
 !IF  "$(CFG)" == "Merge - Win32 Release"
@@ -668,6 +668,10 @@ SOURCE=.\DirFrame.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\DirScan.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\DirView.h
 # End Source File
 # Begin Source File
index f2d97c7..08d4c45 100644 (file)
@@ -1,6 +1,8 @@
 2003-07-24 Kimmo
  PATCH: [ 776525 ] Close doc after failed load
   WinMerge: MainFrm.cpp
+ PATCH: [ 766287 ] Use our own dir traversal (instead of diff's)
+  WinMerge: Diff.cpp DiffContext.h DiffThread.cpp DirDoc.cpp Merge.dsp DirScan.h DirScan.cpp
 
 2003-07-23 Perry
  PATCH: [ 776046 ] Fixes for <Highlight Line Diff> menu item