Add Mtime to the file metadata cache. (#326)

* Add Mtime to the file metadata cache.

* Address comments.
diff --git a/go/pkg/filemetadata/BUILD.bazel b/go/pkg/filemetadata/BUILD.bazel
index 378c3e4..3360c1d 100644
--- a/go/pkg/filemetadata/BUILD.bazel
+++ b/go/pkg/filemetadata/BUILD.bazel
@@ -26,6 +26,7 @@
         "//go/pkg/digest:go_default_library",
         "//go/pkg/testutil:go_default_library",
         "@com_github_google_go_cmp//cmp:go_default_library",
+        "@com_github_google_go_cmp//cmp/cmpopts:go_default_library",
     ],
 )
 
diff --git a/go/pkg/filemetadata/cache_posix_test.go b/go/pkg/filemetadata/cache_posix_test.go
index bff9f08..3b26fb8 100644
--- a/go/pkg/filemetadata/cache_posix_test.go
+++ b/go/pkg/filemetadata/cache_posix_test.go
@@ -28,7 +28,7 @@
 		Digest:       wantDg,
 		IsExecutable: true,
 	}
-	if diff := cmp.Diff(want, got); diff != "" {
+	if diff := cmp.Diff(want, got, ignoreMtime); diff != "" {
 		t.Errorf("Get(%v) returned diff. (-want +got)\n%s", filename, diff)
 	}
 }
diff --git a/go/pkg/filemetadata/cache_test.go b/go/pkg/filemetadata/cache_test.go
index e77bf8e..5104bd0 100644
--- a/go/pkg/filemetadata/cache_test.go
+++ b/go/pkg/filemetadata/cache_test.go
@@ -32,7 +32,7 @@
 		Digest:       wantDg,
 		IsExecutable: false,
 	}
-	if diff := cmp.Diff(want, got); diff != "" {
+	if diff := cmp.Diff(want, got, ignoreMtime); diff != "" {
 		t.Errorf("Get(%v) returned diff. (-want +got)\n%s", filename, diff)
 	}
 	if c.GetCacheHits() != 0 {
@@ -62,7 +62,7 @@
 		if got.Err != nil {
 			t.Errorf("Get(%v) failed. Got error: %v", filename, got.Err)
 		}
-		if diff := cmp.Diff(want, got); diff != "" {
+		if diff := cmp.Diff(want, got, ignoreMtime); diff != "" {
 			t.Errorf("Get(%v) returned diff. (-want +got)\n%s", filename, diff)
 		}
 	}
@@ -91,7 +91,7 @@
 		Digest:       wantDg,
 		IsExecutable: false,
 	}
-	if diff := cmp.Diff(want, got); diff != "" {
+	if diff := cmp.Diff(want, got, ignoreMtime); diff != "" {
 		t.Fatalf("Get(%v) returned diff. (-want +got)\n%s", filename, diff)
 	}
 
@@ -103,7 +103,7 @@
 	if got.Err != nil {
 		t.Errorf("Get(%v) failed. Got error: %v", filename, got.Err)
 	}
-	if diff := cmp.Diff(want, got); diff != "" {
+	if diff := cmp.Diff(want, got, ignoreMtime); diff != "" {
 		t.Errorf("Get(%v) returned diff. (-want +got)\n%s", filename, diff)
 	}
 	if c.GetCacheHits() != 1 {
diff --git a/go/pkg/filemetadata/filemetadata.go b/go/pkg/filemetadata/filemetadata.go
index 80d612a..9242da5 100644
--- a/go/pkg/filemetadata/filemetadata.go
+++ b/go/pkg/filemetadata/filemetadata.go
@@ -3,6 +3,7 @@
 
 import (
 	"os"
+	"time"
 
 	"github.com/bazelbuild/remote-apis-sdks/go/pkg/digest"
 )
@@ -18,6 +19,7 @@
 	Digest       digest.Digest
 	IsExecutable bool
 	IsDirectory  bool
+	MTime        time.Time
 	Err          error
 	Symlink      *SymlinkMetadata
 }
@@ -71,6 +73,7 @@
 		return md
 	}
 	mode := file.Mode()
+	md.MTime = file.ModTime()
 	md.IsExecutable = (mode & 0100) != 0
 	if mode.IsDir() {
 		md.IsDirectory = true
diff --git a/go/pkg/filemetadata/filemetadata_test.go b/go/pkg/filemetadata/filemetadata_test.go
index 26e4ea8..8e172f0 100644
--- a/go/pkg/filemetadata/filemetadata_test.go
+++ b/go/pkg/filemetadata/filemetadata_test.go
@@ -5,10 +5,16 @@
 	"os"
 	"path/filepath"
 	"testing"
+	"time"
 
 	"github.com/bazelbuild/remote-apis-sdks/go/pkg/digest"
 	"github.com/bazelbuild/remote-apis-sdks/go/pkg/testutil"
 	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+)
+
+var (
+	ignoreMtime = cmpopts.IgnoreFields(Metadata{}, "MTime")
 )
 
 func TestComputeFiles(t *testing.T) {
@@ -33,10 +39,12 @@
 	}
 	for _, tc := range tests {
 		t.Run(tc.name, func(t *testing.T) {
+			before := time.Now().Truncate(time.Second)
 			filename, err := testutil.CreateFile(t, tc.executable, tc.contents)
 			if err != nil {
 				t.Fatalf("Failed to create tmp file for testing digests: %v", err)
 			}
+			after := time.Now().Truncate(time.Second).Add(time.Second)
 			defer os.RemoveAll(filename)
 			got := Compute(filename)
 			if got.Err != nil {
@@ -46,9 +54,12 @@
 				Digest:       digest.NewFromBlob([]byte(tc.contents)),
 				IsExecutable: tc.executable,
 			}
-			if diff := cmp.Diff(want, got); diff != "" {
+			if diff := cmp.Diff(want, got, ignoreMtime); diff != "" {
 				t.Errorf("Compute(%v) returned diff. (-want +got)\n%s", filename, diff)
 			}
+			if got.MTime.Before(before) || got.MTime.After(after) {
+				t.Errorf("Compute(%v) returned MTime %v, want time in (%v, %v).", filename, got.MTime, before, after)
+			}
 		})
 	}
 }
@@ -109,7 +120,7 @@
 				IsExecutable: tc.executable,
 			}
 
-			if diff := cmp.Diff(want, got); diff != "" {
+			if diff := cmp.Diff(want, got, ignoreMtime); diff != "" {
 				t.Errorf("Compute(%v) returned diff. (-want +got)\n%s", symlinkPath, diff)
 			}
 		})