#region GPL
// Copyright (c) Evan Hazlett, 2005
// Sourcefile: Engine.cs
//
// 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 2 of the License, or
// (at your option) any later version.
//
// This program is distributed WITHOUT ANY WARRANTY.
// See the GNU General Public License for more details.
//
// Evan Hazlett - linx@pixolight.com
//
#endregion
#region Using Directives
using System;
using System.Data;
using System.IO;
using System.Diagnostics;
using System.Threading;
#endregion
namespace FileSync.Core{
/// <summary>
/// Engine for file and directory comparison and synchronization.
/// </summary>
public class Engine
{
#region Fields
private DataTable dtSrcItems;
private DataTable dtDestItems;
#endregion
#region Constructor
public Engine ()
{
// create data tables
CreateDataTables();
}
#endregion
#region Private Methods
/// <summary>
/// Creates Data Tables needed for the UI
/// </summary>
private void CreateDataTables ()
{
// initialize data tables
dtSrcItems = new DataTable ( "srcItems" );
dtDestItems = new DataTable ( "destItems" );
// create src columns
//
// create path column with type string
DataColumn dcSrcPath = new DataColumn ( "path", Type.GetType ( "System.String" ) );
// create creation column with type string
DataColumn dcSrcCreatedDate = new DataColumn ( "createdDate", Type.GetType ( "System.String" ) );
// create directory column with type boolean
DataColumn dcSrcDirectory = new DataColumn ( "directory", Type.GetType ( "System.Boolean" ) );
// create dest columns
//
// create path column with type string
DataColumn dcDestPath = new DataColumn ( "path", Type.GetType ( "System.String" ) );
// create creation column with type string
DataColumn dcDestCreatedDate = new DataColumn ( "createdDate", Type.GetType ( "System.String" ) );
// create directory column with type boolean
DataColumn dcDestDirectory = new DataColumn ( "directory", Type.GetType ( "System.Boolean" ) );
// add columns to tables
dtSrcItems.Columns.Add ( dcSrcPath );
dtSrcItems.Columns.Add ( dcSrcCreatedDate );
dtSrcItems.Columns.Add ( dcSrcDirectory );
dtDestItems.Columns.Add ( dcDestPath );
dtDestItems.Columns.Add ( dcDestCreatedDate );
dtDestItems.Columns.Add ( dcDestDirectory );
}
private void GetSourceItems ( string srcDirectory )
{
Debug.WriteLine ( "Getting contents of source directory: " + srcDirectory );
// create new DirectoryInfo object
DirectoryInfo rootSrcDir = new DirectoryInfo ( srcDirectory );
// get all files and directories
FileSystemInfo[] allItems = rootSrcDir.GetFileSystemInfos();
// loop and test for file or directory
foreach ( FileSystemInfo item in allItems )
{
// create new row
DataRow row = dtSrcItems.NewRow();
// if directory set directory to true
if ( item is DirectoryInfo )
{
row["path"] = item.FullName;
row["createdDate"] = item.CreationTime.ToShortDateString();
row["directory"] = true;
dtSrcItems.Rows.Add ( row );
Debug.WriteLine ( item.FullName );
GetSourceItems ( item.FullName );
}
if ( item is FileInfo )
{
row["path"] = item.FullName;
row["createdDate"] = item.CreationTime.ToShortDateString();
row["directory"] = false;
dtSrcItems.Rows.Add ( row );
Debug.WriteLine ( item.FullName );
}
}
}
private void GetDestItems ( string destDirectory )
{
Debug.WriteLine ( "Getting contents of destination directory: " + destDirectory );
// create new DirectoryInfo object
DirectoryInfo rootDestDir = new DirectoryInfo ( destDirectory );
// get all files and directories
FileSystemInfo[] allItems = rootDestDir.GetFileSystemInfos();
// loop and test for file or directory
foreach ( FileSystemInfo item in allItems )
{
// create new row
DataRow row = dtDestItems.NewRow();
// if directory set directory to true
if ( item is DirectoryInfo )
{
row["path"] = item.FullName;
row["createdDate"] = item.CreationTime.ToShortDateString();
row["directory"] = true;
dtDestItems.Rows.Add ( row );
Debug.WriteLine ( item.FullName );
GetDestItems ( item.FullName );
}
if ( item is FileInfo )
{
row["path"] = item.FullName;
row["createdDate"] = item.CreationTime.ToShortDateString();
row["directory"] = false;
dtDestItems.Rows.Add ( row );
Debug.WriteLine ( item.FullName );
}
}
}
/// <summary>
/// Synchronizes all files and directories from source directory to destination directory. - Uses method <code>SyncFiles()</code>
/// </summary>
/// <param name="srcDir">Source directory as a string.</param>
/// <param name="destDir">Destination directory as a string.</param>
private void Sync ( string srcDir, string destDir )
{
// create a directory info object to work with directory
DirectoryInfo diSrc = new DirectoryInfo ( srcDir );
// get all directories in src
DirectoryInfo[] srcDirs = diSrc.GetDirectories();
// sync files in root
SyncFiles ( srcDir, destDir );
// check for directories and create as necessary
foreach ( DirectoryInfo dir in srcDirs )
{
// check if directory exists
if ( !Directory.Exists ( destDir + "\\" + dir.Name ) )
{
Directory.CreateDirectory ( destDir + "\\" + dir.Name );
}
// invoke CreateSubDirs for loop
SyncAll ( dir.FullName, destDir + "\\" + dir.Name );
}
}
/// <summary>
/// Synchronizes all files from source directory to destination directory.
/// </summary>
/// <param name="srcDir">Source directory as a string.</param>
/// <param name="destDir">Destination directory as a string.</param>
private void SyncFiles ( string srcDir, string destDir )
{
// create a directory info object to work with directory
DirectoryInfo diSrc = new DirectoryInfo ( srcDir );
// get all files in src
FileInfo[] srcFiles = diSrc.GetFiles();
// check for directories and create as necessary
foreach ( FileInfo file in srcFiles )
{
// if file doesn't exist, copy
if ( !File.Exists ( destDir + "\\" + file.Name ) )
{
File.Copy ( file.FullName, destDir + "\\" + file.Name );
}
// if file exists, compare
else
{
// compare files
switch ( CompareFiles ( file.FullName, destDir + "\\" + file.Name ) )
{
// source is newer
case "->":
File.Copy ( file.FullName, destDir + "\\" + file.Name, true );
break;
// dest is newer
case "<-":
File.Copy ( destDir + "\\" + file.Name, file.FullName, true );
break;
// files are equal
case "=":
break;
}
}
}
}
#endregion
#region Public Methods
/// <summary>
/// The main compare method. Gets all files in both source and destination directories, and puts them into the datatable.
/// </summary>
/// <param name="sourceDirectory">The source directory path as a string.</param>
/// <param name="destinationDirectory">The destination directory path as a string.</param>
public void Compare ( string sourceDirectory, string destinationDirectory )
{
GetSourceItems ( sourceDirectory );
GetDestItems ( destinationDirectory );
}
/// <summary>
/// Compares files based on date.
/// </summary>
/// <param name="file1">Source file.</param>
/// <param name="file2">Destination file.</param>
/// <returns>Symbol determining which should be synchonized.</returns>
public string CompareFiles ( string file1, string file2 )
{
FileInfo f1 = new FileInfo ( file1 );
FileInfo f2 = new FileInfo ( file2 );
#region Compare by last time accessed
// compare the year
if ( File.GetLastWriteTime ( file1 ).Year > File.GetLastWriteTime ( file2 ).Year )
{
// file1 is newer
return "->";
}
else if ( File.GetLastWriteTime ( file1 ).Year < File.GetLastWriteTime ( file2 ).Year )
{
// file2 is newer
return "<-";
}
// the year is the same, compare furthur
else
{
// compare months
if ( File.GetLastWriteTime ( file1 ).Month > File.GetLastWriteTime ( file2 ).Month )
{
// file1 is newer
return "->";
}
else if ( File.GetLastWriteTime ( file1 ).Month < File.GetLastWriteTime ( file2 ).Month )
{
// file2 is newer
return "<-";
}
// the month is the same, compare furthur
else
{
// compare days
if ( File.GetLastWriteTime ( file1 ).Day > File.GetLastWriteTime ( file2 ).Day )
{
// file1 is newer
return "->";
}
else if ( File.GetLastWriteTime ( file1 ).Day < File.GetLastWriteTime ( file2 ).Day )
{
// file2 is newer
return "<-";
}
// the day is the same, compare furthur
else
{
// compare hour
if ( File.GetLastWriteTime ( file1 ).Hour > File.GetLastWriteTime ( file2 ).Hour )
{
// file1 is newer
return "->";
}
else if ( File.GetLastWriteTime ( file1 ).Hour < File.GetLastWriteTime ( file2 ).Hour )
{
// file2 is newer
return "<-";
}
// the hour is the same, compare furthur
else
{
// compare minutes
if ( File.GetLastWriteTime ( file1 ).Minute > File.GetLastWriteTime ( file2 ).Minute )
{
// file1 is newer
return "->";
}
else if ( File.GetLastWriteTime ( file1 ).Minute < File.GetLastWriteTime ( file2 ).Minute )
{
// file2 is newer
return "<-";
}
// the minute is the same, compare furthur
else
{
// compare seconds and file sizes
if ( File.GetLastWriteTime ( file1 ).Second > File.GetLastWriteTime ( file2 ).Second && f1.Length != f2.Length )
{
// file1 is newer
return "->";
}
else if ( File.GetLastWriteTime ( file1 ).Second < File.GetLastWriteTime ( file2 ).Second && f1.Length != f2.Length)
{
// file2 is newer
return "<-";
}
else
{
// seconds match and files are same size; consider equal
return "=";
}
}
}
}
}
}
#endregion
}
/// <summary>
/// Synchronizes all files and directories from source to destination and vice versa.
/// </summary>
/// <param name="sourceDirectory">Source directory as a string.</param>
/// <param name="destinationDirectory">Destination directory as a string.</param>
public void SyncAll ( string sourceDirectory, string destinationDirectory )
{
// sync source to dest
Sync ( sourceDirectory, destinationDirectory );
// sync dest to source
Sync ( destinationDirectory, sourceDirectory );
}
/// <summary>
/// Synchronizes all files and directories from source to destination.
/// </summary>
/// <param name="sourceDirectory">Source directory as a string.</param>
/// <param name="destinationDirectory">Destination directory as string.</param>
public void SyncSourceToDest ( string sourceDirectory, string destinationDirectory )
{
// sync source to destination
Sync ( sourceDirectory, destinationDirectory );
}
/// <summary>
/// Synchronizes all files and directories from destination to source.
/// </summary>
/// <param name="sourceDirectory">Source directory as a string.</param>
/// <param name="destinationDirectory">Destination directory as string.</param>
public void SyncDestToSource ( string sourceDirectory, string destinationDirectory )
{
// sync destination to source
Sync ( destinationDirectory, sourceDirectory );
}
#endregion
#region Properties
/// <summary>
/// Gets the Source DataTable of Files and Directories.
/// </summary>
public DataTable SourceFiles
{
get
{
return dtSrcItems;
}
}
/// <summary>
/// Gets the Destination DataTable of Files and Directories.
/// </summary>
public DataTable DestinationFiles
{
get
{
return dtDestItems;
}
}
#endregion
}
}
|