Bugs item #1033631, was opened at 2004-09-24 05:18
Message generated for change (Comment added) made by ianm74
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=402868&aid=1033631&group_id=31650

Category: Tasks
Group: 0.85
Status: Open
Resolution: None
Priority: 5
Submitted By: thomas strauss (tstrauss)
Assigned to: Nobody/Anonymous (nobody)
Summary: <touch> works not on FAT32 

Initial Comment:
The <touch> works not on FAT32 partitions. The test
TouchTaskTest.Test_File_Millis and its friend working
with the fileset are failing. I've checked this
behaviour on a Win2000 and WinXP system. The reason is
in the FAT32 filesystem the time begins to count in the
1980 when the first dos like OS was developed. Therefor
in the test the millisseconds should be chosen after
that date. After fixing this i discovered a bug in the
TouchTask itself. The milliseconds should be parsed as
an Int64 value to prevent an overflow. The description
of the  <touch> task states it behaves like the unix
touch command. But there the resolution is something
like 1 sec and then Int32 reaches to the year 2037 or
so. I've attached the files which solves the issues.

Cheers 

Thomas Strauss

TouchTaskTest.cs
---------------------
// NAnt - A .NET build tool
// Copyright (C) 2001-2002 Gerry Shaw
//
// 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 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., 59 Temple Place, Suite 330,
Boston, MA  02111-1307  USA

// Jay Turpin ([EMAIL PROTECTED])
// Gerry Shaw ([EMAIL PROTECTED])

using System;
using System.Collections.Specialized;
using System.IO;
using System.Globalization;

using NUnit.Framework;

using NAnt.Core.Tasks;
using Tests.NAnt.Core.Util;

namespace Tests.NAnt.Core.Tasks {
    [TestFixture]
    public class TouchTaskTest : BuildTestBase {
        const string _format = @"<?xml version='1.0' ?>
            <project>
                <touch {0}>{1}</touch>
            </project>";

                private static long TICKS_PER_MILLISECOND =
TimeSpan.FromMilliseconds(1).Ticks;
                
        StringCollection _fileList = new
StringCollection();

        /// <summary>Create the text fixture.</summary>
        [SetUp]
        protected override void SetUp() {
            base.SetUp();

            // add 3 directories
           
Directory.CreateDirectory(Path.Combine(TempDirName,
"dir1"));
           
Directory.CreateDirectory(Path.Combine(TempDirName,
"dir2"));
           
Directory.CreateDirectory(Path.Combine(TempDirName,
"dir3"));

            // add file names
            _fileList.Add(Path.Combine(TempDirName,
"file1.txt"));
            _fileList.Add(Path.Combine(TempDirName,
"file2.txt"));
            _fileList.Add(Path.Combine(TempDirName,
Path.Combine("dir1" ,"file3.tab")));
            _fileList.Add(Path.Combine(TempDirName,
Path.Combine("dir1" ,"file4.txt")));
            _fileList.Add(Path.Combine(TempDirName,
Path.Combine("dir2" ,"file5.tab")));
            _fileList.Add(Path.Combine(TempDirName,
Path.Combine("dir2" ,"file6.txt")));


            // add some text to each file, just for fun ;)
            for (int i = 0; i < _fileList.Count; i++) {
                TempFile.Create(_fileList[i]);
            }
        }

        [Test]
        public void Test_File_DateTime() {

            DateTime newTouchDate =
DateTime.Parse("01/01/1980");
            string fileName = _fileList[0];
            RunBuild(FormatBuildFile("file='" +
fileName + "' datetime='" +
newTouchDate.ToString(CultureInfo.InvariantCulture) +
"'"));

            FileInfo file = new FileInfo(fileName);
            DateTime lastTouchDate = file.LastWriteTime;

           
Assert.IsTrue(newTouchDate.Equals(lastTouchDate), "File
not touched");

            // Make sure another file is NOT touched
            fileName = _fileList[1];
            file = new FileInfo(fileName);
            lastTouchDate = file.LastWriteTime;

           
Assert.IsFalse(newTouchDate.Equals(lastTouchDate),
"Wrong file was touched");
        }

        [Test]
        public void Test_File_Millis() {
            // <touch file='myfile' millis='1000000000'/>

            string fileName = _fileList[0];
                        
                        long milliSeconds =
((DateTime.Parse("01/01/1980").Ticks -
DateTime.Parse("01/01/1970").Ticks) /
TICKS_PER_MILLISECOND);
                        DateTime newTouchDate =
DateTime.Parse("01/01/1970").Add(TimeSpan.FromMilliseconds(milliSeconds));
                        
            RunBuild(FormatBuildFile("file='" +
fileName + "' millis='" + milliSeconds.ToString() + "'"));
            FileInfo file = new FileInfo(fileName);
            DateTime lastTouchDate = file.LastWriteTime;

           
Assert.IsTrue(newTouchDate.Equals(lastTouchDate),
"Wrong touch date");

            // Make sure another file is NOT touched
            fileName = _fileList[1];
            file = new FileInfo(fileName);
            lastTouchDate = file.LastWriteTime;

           
Assert.IsFalse(newTouchDate.Equals(lastTouchDate),
"Wrong file touched");
        }

        [Test]
       public void Test_File_Default() {
            // avoid test failure on fast machines and
linux
            System.Threading.Thread.Sleep(1000);

            string fileName = _fileList[0];
            DateTime newTouchDate = DateTime.Now;

            // avoid test failure on fast machines and
linux
            System.Threading.Thread.Sleep(1000);

            RunBuild(FormatBuildFile("file='" +
fileName + "'"));

            FileInfo file = new FileInfo(fileName);
            DateTime lastTouchDate = file.LastWriteTime;

            // Can only ensure that Now() is greater or
equal to the file date
           
Assert.IsTrue(lastTouchDate.CompareTo(newTouchDate) >=
0, "Touch date incorrect");

            // Make sure another file is NOT touched
            fileName = _fileList[1];
            file = new FileInfo(fileName);
            lastTouchDate = file.LastWriteTime;

           
Assert.IsFalse(newTouchDate.Equals(lastTouchDate),
"Wrong file touched");
        }

        [Test]
       public void Test_Same_File_Twice() {
            // <touch file='myfile' />
            // <touch file='myfile' />
            // Old code used to lock the file -
shouldn't now, allowing us to mess with it between runs

            string fileName = _fileList[0];

            // Get rid of the file first
            File.Delete(fileName);

            RunBuild(FormatBuildFile("file='" +
fileName + "'"));
            Assert.IsTrue(File.Exists(fileName), "File
doesn't exist!");
            File.Delete(fileName);

            RunBuild(FormatBuildFile("file='" +
fileName + "'"));
            Assert.IsTrue(File.Exists(fileName), "File
doesn't exist!");
            File.Delete(fileName);
        }

        [Test]
        public void Test_FileSet_DateTime() {
            // <touch datetime="01/01/1980 00:00">
            //   <fileset dir="src_dir"/>
            // </touch>

            DateTime newTouchDate =
DateTime.Parse("01/01/1980");          
            RunBuild(FormatBuildFile("datetime='" +
newTouchDate.ToString(CultureInfo.InvariantCulture) +
"'","<fileset basedir='" + TempDirName + "'><include
name='**' /></fileset>"));

            for (int i = 0; i < _fileList.Count; i++) {
                FileInfo file = new FileInfo(_fileList[i]);
                DateTime lastTouchDate =
file.LastWriteTime;

               
Assert.IsTrue(newTouchDate.Equals(lastTouchDate),
"Touch: fileset, datetime, " + _fileList[i]);
            }
        }

        [Test]
        public void Test_FileSet_Millis() {
            // <touch millis="100000">
            //   <fileset dir="src_dir"/>
            //</touch>

                        long milliSeconds =
((DateTime.Parse("01/01/1980").Ticks -
DateTime.Parse("01/01/1970").Ticks) /
TICKS_PER_MILLISECOND);
                        DateTime newTouchDate =
DateTime.Parse("01/01/1970").Add(TimeSpan.FromMilliseconds(milliSeconds));
          
            RunBuild(FormatBuildFile("millis='" +
milliSeconds.ToString(CultureInfo.InvariantCulture) +
"'","<fileset basedir='" + TempDirName + "'><include
name='**' /></fileset>"));

            for (int i = 0; i < _fileList.Count; i++) {

                FileInfo file = new FileInfo(_fileList[i]);
                DateTime lastTouchDate =
file.LastWriteTime;

               
Assert.IsTrue(newTouchDate.Equals(lastTouchDate),
"Touch: fileset, millis, " + _fileList[i]);
            }
        }

        [Test]
        public void Test_FileSet_Default() {
            DateTime newTouchDate = DateTime.Now;

            // avoid test failure on linux
            System.Threading.Thread.Sleep(1000);
          
            RunBuild(FormatBuildFile("","<fileset
basedir='" + TempDirName + "'><include name='**'
/></fileset>"));

            for (int i = 0; i < _fileList.Count; i++) {
                FileInfo file = new FileInfo(_fileList[i]);
                DateTime lastTouchDate =
file.LastWriteTime;

               
Assert.IsTrue(lastTouchDate.CompareTo(newTouchDate) >=
0, "Touch: fileset ONLY, " + _fileList[i]);
            }
        }

        private string FormatBuildFile(string options) {
            return FormatBuildFile(options, "");
        }

        private string FormatBuildFile(string options,
string nestedElements) {
            return
String.Format(CultureInfo.InvariantCulture, _format,
options, nestedElements);
        }
    }
}

---------------------

TouchTest.cs
---------------------
// NAnt - A .NET build tool
// Copyright (C) 2001-2002 Gerry Shaw
//
// 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 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., 59 Temple Place, Suite 330,
Boston, MA  02111-1307  USA
//
// Jay Turpin ([EMAIL PROTECTED])
// Gerry Shaw ([EMAIL PROTECTED])

using System;
using System.IO;
using System.Globalization;

using NAnt.Core.Attributes;
using NAnt.Core.Types;
using NAnt.Core.Util;

namespace NAnt.Core.Tasks {
    /// <summary>
    /// Touches a file or set of files -- corresponds
to the Unix touch command.  
    /// </summary>
    /// <remarks>
    /// <para>
    /// If the file specified in the single-file case
does not exist, the task 
    /// will create it.
    /// </para>
    /// </remarks>
    /// <example>
    ///   <para>Touch the <c>Main.cs</c> file.  The
current time is used.</para>
    ///   <code>
    ///     <![CDATA[
    /// <touch file="Main.cs" />
    ///     ]]>
    ///   </code>
    /// </example>
    /// <example>
    ///   <para>Touch all executable files in the
current directory and its subdirectories.</para>
    ///   <code>
    ///     <![CDATA[
    /// <touch>
    ///     <fileset>
    ///         <include name="**/*.exe" />
    ///         <include name="**/*.dll" />
    ///     </fileset>
    /// </touch>
    ///     ]]>
    ///   </code>
    /// </example>
    [TaskName("touch")]
    public class TouchTask : Task {
        #region Private Instance Fields

                private static long TICKS_PER_MILLISECOND =
TimeSpan.FromMilliseconds(1).Ticks;
                
        private FileInfo _file;
        private string _millis;
        private string _datetime;
        private FileSet _fileset = new FileSet();

        #endregion Private Instance Fields

        #region Public Instance Properties

        /// <summary>
        /// The file to touch.
        /// </summary>
        [TaskAttribute("file")]
        public FileInfo File {
            get { return _file; }
            set { _file = value; }
        }

        /// <summary>
        /// Specifies the new modification time of the
file(s) in milliseconds 
        /// since midnight Jan 1 1970.
        /// </summary>
        [TaskAttribute("millis")]
        public string Millis {
            get { return _millis; }
            set { _millis = value; }
        }

        /// <summary>
        /// Specifies the new modification time of the
file in the format 
        /// MM/DD/YYYY HH:MM AM_or_PM.
        /// </summary>
        [TaskAttribute("datetime")]
        public string Datetime {
            get { return _datetime; }
            set { _datetime = value; }
        }

        /// <summary>
        /// Used to select files that should be touched.
        /// </summary>
        [BuildElement("fileset")]
        public FileSet TouchFileSet {
            get { return _fileset; }
            set { _fileset = value; }
        }

        #endregion Public Instance Properties

        #region Override implementation of Task

        /// <summary>
        /// Ensures the supplied attributes are valid.
        /// </summary>
        /// <param name="taskNode">Xml node used to
define this task instance.</param>
        protected override void
InitializeTask(System.Xml.XmlNode taskNode) {
            // limit task to either millis or a date string
            if (Millis != null && Datetime != null) {
                throw new BuildException("Cannot
specify 'millis' and 'datetime' in the same touch
task.", Location);
            }

            // limit task to touching either a file or
fileset
            if (File != null &&
TouchFileSet.Includes.Count != 0) {
                throw new BuildException("Cannot
specify both 'file' attribute" 
                    + " and use <fileset> in the same
<touch> task.", Location);
            }
        }

        protected override void ExecuteTask() {
            DateTime touchDateTime = DateTime.Now;

            // ensure base directory is set, even if
fileset was not initialized
            // from XML
            if (TouchFileSet.BaseDirectory == null) {
                TouchFileSet.BaseDirectory = new
DirectoryInfo(Project.BaseDirectory);
            }

            if (Millis != null) {
                touchDateTime =
GetDateTime(Convert.ToInt64(Millis,
CultureInfo.InvariantCulture));
            } else if (Datetime != null) {
                touchDateTime = GetDateTime(Datetime);
            }

            // try to touch specified file
            if (File != null) {
                // touch file
                TouchFile(File.FullName, touchDateTime);
            } else {
                // touch files in fileset
                // only use the file set if file
attribute has NOT been set
                foreach (string path in
TouchFileSet.FileNames) {
                    TouchFile(path, touchDateTime);
                }
            }
        }

        #endregion Override implementation of Task

        #region Private Instance Methods        

        private void TouchFile(string path, DateTime
touchDateTime) {
            try {
                if (System.IO.File.Exists(path)) {
                    Log(Level.Verbose, "Touching file
'{0}' with '{1}'.", 
                        path,
touchDateTime.ToString(CultureInfo.InvariantCulture));
                } else {
                    Log(Level.Verbose, "Creating file
'{0}' with '{1}'.", 
                        path,
touchDateTime.ToString(CultureInfo.InvariantCulture));
                    // create the file (and ensure
stream is closed)
                    using (FileStream fs =
System.IO.File.Create(path)) {
                    }
                }
                System.IO.File.SetLastWriteTime(path,
touchDateTime);
            } catch (Exception ex) {
                string msg =
string.Format(CultureInfo.InvariantCulture, 
                    "Cannot touch file '{0}'.", path);

                if (FailOnError) {
                    throw new BuildException(msg,
Location, ex);
                }

                // swallow any errors and move on
                Log(Level.Verbose, msg + " " + ex.Message);
            }
        }

        private DateTime GetDateTime(string dateText){
            DateTime touchDateTime = new DateTime();

            if (!StringUtils.IsNullOrEmpty(dateText)) {
                touchDateTime =
DateTime.Parse(dateText, CultureInfo.InvariantCulture);
            } else {
                touchDateTime = DateTime.Now;
            }
            return touchDateTime;
        }

        private DateTime GetDateTime(long milliSeconds) {
            DateTime touchDateTime =
DateTime.Parse("01/01/1970 00:00:00",
CultureInfo.InvariantCulture).
                                Add(TimeSpan.FromMilliseconds(milliSeconds));
            return touchDateTime;
        }

        #endregion Private Instance Methods
    }
}
---------------------

----------------------------------------------------------------------

>Comment By: Ian MacLean (ianm74)
Date: 2004-09-28 15:46

Message:
Logged In: YES 
user_id=321872

Thanks for the bug report Thomas,
I'd be happy to look at this but would you first be able to
attach the files rather than pasting their contents inline ?
It makes it much easier to apply the difference to current
cvs if the formatting has been preserved.


----------------------------------------------------------------------

Comment By: thomas strauss (tstrauss)
Date: 2004-09-28 06:15

Message:
Logged In: YES 
user_id=1067181

Hello out there, does any body feels responsible for the 
bug-entry. I've provided also a possible solution. This was 
quite some effort to puzzle out waht was going wrong.

Cheere 

Thomas

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=402868&aid=1033631&group_id=31650


-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170
Project Admins to receive an Apple iPod Mini FREE for your judgement on
who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php
_______________________________________________
nant-developers mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/nant-developers

Reply via email to