Inheritance: Revision
		static void GetDirectoryVersionInfoCore (LibGit2Sharp.Repository repo, GitRevision rev, FilePath directory, List<VersionInfo> versions, bool recursive)
		{
			var relativePath = repo.ToGitPath (directory);
			var status = repo.RetrieveStatus (new StatusOptions {
				PathSpec = relativePath != "." ? new [] { relativePath } : null,
				IncludeUnaltered = true,
			});

			versions.AddRange (status.Added.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledAdd, rev, VersionStatus.Versioned, null)));
			versions.AddRange (status.Ignored.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Ignored, rev, VersionStatus.Unversioned, null)));
			versions.AddRange (status.Missing.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledDelete, rev, VersionStatus.Versioned, null)));
			versions.AddRange (status.Modified.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.Modified, rev, VersionStatus.Versioned, null)));
			versions.AddRange (status.Removed.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledDelete, rev, VersionStatus.Versioned, null)));
			versions.AddRange (status.RenamedInIndex.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledReplace, rev, VersionStatus.Versioned, null)));
			versions.AddRange (status.RenamedInWorkDir.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned | VersionStatus.ScheduledReplace, rev, VersionStatus.Versioned, null)));
			versions.AddRange (status.Unaltered.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Versioned, rev, VersionStatus.Versioned, null)));
			versions.AddRange (status.Untracked.Select (s => new VersionInfo (
				repo.FromGitPath (s.FilePath), "", false, VersionStatus.Unversioned, rev, VersionStatus.Unversioned, null)));

			foreach (var conflict in repo.Index.Conflicts) {
				FilePath path = conflict.Ours.Path;
				if (path.IsChildPathOf (directory))
					versions.Add (new VersionInfo (
						repo.FromGitPath (path), "", false, VersionStatus.Versioned | VersionStatus.Conflicted, rev, VersionStatus.Versioned, null));
			}

			if (!recursive)
				versions.RemoveAll (v => v.LocalPath.ParentDirectory != directory);
		}
Exemple #2
0
		internal GitRevision GetPreviousRevisionFor (GitRevision revision)
		{
			ObjectId id = revision.GitRepository.Resolve (revision.ToString () + "^");
			if (id == null)
				return null;
			return new GitRevision (this, revision.GitRepository, id.Name);
		}
		VersionInfo[] GetDirectoryVersionInfo (FilePath localDirectory, IEnumerable<FilePath> localFileNames, bool getRemoteStatus, bool recursive)
		{
			var versions = new List<VersionInfo> ();

			if (localFileNames != null) {
				var localFiles = new List<FilePath> ();
				foreach (var group in GroupByRepository (localFileNames)) {
					var repository = group.Key;
					GitRevision arev;
					if (!versionInfoCacheEmptyRevision.TryGetValue (repository, out arev)) {
						arev = new GitRevision (this, repository, null);
						versionInfoCacheEmptyRevision.Add (repository, arev);
					}
					foreach (var p in group) {
						if (Directory.Exists (p)) {
							if (recursive)
								versions.AddRange (GetDirectoryVersionInfo (p, getRemoteStatus, true));
							versions.Add (new VersionInfo (p, "", true, VersionStatus.Versioned, arev, VersionStatus.Versioned, null));
						} else
							localFiles.Add (p);
					}
				}
				// No files to check, we are done
				if (localFiles.Count != 0) {
					foreach (var group in GroupByRepository (localFileNames)) {
						var repository = group.Key;

						GitRevision rev = null;
						Commit headCommit = GetHeadCommit (repository);
						if (headCommit != null) {
							if (!versionInfoCacheRevision.TryGetValue (repository, out rev)) {
								rev = new GitRevision (this, repository, headCommit);
								versionInfoCacheRevision.Add (repository, rev);
							} else if (rev.Commit != headCommit) {
								rev = new GitRevision (this, repository, headCommit);
								versionInfoCacheRevision [repository] = rev;
							}
						}

						GetFilesVersionInfoCore (repository, rev, group.ToList (), versions);
					}
				}
			} else {
				var directories = new List<FilePath> ();
				CollectFiles (directories, localDirectory, recursive);

				// Set directory items as Versioned.
				GitRevision arev = null;
				foreach (var group in GroupByRepository (directories)) {
					var repository = group.Key;
					if (!versionInfoCacheEmptyRevision.TryGetValue (repository, out arev)) {
						arev = new GitRevision (this, repository, null);
						versionInfoCacheEmptyRevision.Add (repository, arev);
					}
					foreach (var p in group)
						versions.Add (new VersionInfo (p, "", true, VersionStatus.Versioned, arev, VersionStatus.Versioned, null));
				}

				Commit headCommit = GetHeadCommit (RootRepository);
				if (headCommit != null) {
					if (!versionInfoCacheRevision.TryGetValue (RootRepository, out arev)) {
						arev = new GitRevision (this, RootRepository, headCommit);
						versionInfoCacheRevision.Add (RootRepository, arev);
					} else if (arev.Commit != headCommit) {
						arev = new GitRevision (this, RootRepository, headCommit);
						versionInfoCacheRevision [RootRepository] = arev;
					}
				}

				GetDirectoryVersionInfoCore (RootRepository, arev, localDirectory.CanonicalPath, versions, recursive);
			}

			return versions.ToArray ();
		}
		static void GetFilesVersionInfoCore (LibGit2Sharp.Repository repo, GitRevision rev, List<FilePath> localPaths, List<VersionInfo> versions)
		{
			foreach (var file in repo.ToGitPath (localPaths)) {
				var status = repo.RetrieveStatus (file);
				VersionStatus fstatus = VersionStatus.Versioned;

				if (status != FileStatus.Unaltered) {
					if ((status & FileStatus.NewInIndex) != 0)
						fstatus |= VersionStatus.ScheduledAdd;
					else if ((status & (FileStatus.DeletedFromIndex | FileStatus.DeletedFromWorkdir)) != 0)
						fstatus |= VersionStatus.ScheduledDelete;
					else if ((status & (FileStatus.TypeChangeInWorkdir | FileStatus.ModifiedInWorkdir)) != 0)
						fstatus |= VersionStatus.Modified;
					else if ((status & (FileStatus.RenamedInIndex | FileStatus.RenamedInWorkdir)) != 0)
						fstatus |= VersionStatus.ScheduledReplace;
					else if ((status & (FileStatus.Nonexistent | FileStatus.NewInWorkdir)) != 0)
						fstatus = VersionStatus.Unversioned;
					else if ((status & FileStatus.Ignored) != 0)
						fstatus = VersionStatus.Ignored;
				}

				if (repo.Index.Conflicts [file] != null)
					fstatus = VersionStatus.Versioned | VersionStatus.Conflicted;

				versions.Add (new VersionInfo (repo.FromGitPath (file), "", false, fstatus, rev, fstatus == VersionStatus.Ignored ? VersionStatus.Unversioned : VersionStatus.Versioned, null));
			}
		}
		VersionInfo[] GetDirectoryVersionInfo (FilePath localDirectory, string fileName, bool getRemoteStatus, bool recursive)
		{
			HashSet<FilePath> existingFiles = new HashSet<FilePath> ();
			if (fileName != null) {
				FilePath fp = localDirectory.Combine (fileName).CanonicalPath;
				if (File.Exists (fp))
					existingFiles.Add (fp);
			} else
				CollectFiles (existingFiles, localDirectory, recursive);
			
			GitRevision rev;
			var headCommit = GetHeadCommit ();
			if (headCommit != null)
				rev = new GitRevision (this, headCommit.Id.Name);
			else
				rev = null;
			List<VersionInfo> versions = new List<VersionInfo> ();
			FilePath p = fileName != null ? localDirectory.Combine (fileName) : localDirectory;
			p = p.CanonicalPath;
			
			RepositoryStatus status;
			if (fileName != null)
				status = GitUtil.GetFileStatus (repo, p);
			else
				status = GitUtil.GetDirectoryStatus (repo, localDirectory, recursive);
			
			HashSet<string> added = new HashSet<string> ();
			
			Action<IEnumerable<string>, VersionStatus> AddFiles = delegate(IEnumerable<string> files, VersionStatus fstatus) {
				foreach (string file in files) {
					if (!added.Add (file))
						continue;
					FilePath statFile = FromGitPath (file);
					existingFiles.Remove (statFile.CanonicalPath);
					VersionInfo vi = new VersionInfo (statFile, "", false, fstatus, rev, VersionStatus.Versioned, null);
					versions.Add (vi);
				}
			};
			
			AddFiles (status.Added, VersionStatus.Versioned | VersionStatus.ScheduledAdd);
			AddFiles (status.Modified, VersionStatus.Versioned | VersionStatus.Modified);
			AddFiles (status.Removed, VersionStatus.Versioned | VersionStatus.ScheduledDelete);
			AddFiles (status.Missing, VersionStatus.Versioned | VersionStatus.ScheduledDelete);
			AddFiles (status.MergeConflict, VersionStatus.Versioned | VersionStatus.Conflicted);
			AddFiles (status.Untracked, VersionStatus.Unversioned);
			
						/*				else if (staged == 'R') {
					// Renamed files are in reality files delete+added to a different location.
					existingFiles.Remove (srcFile.CanonicalPath);
					VersionInfo rvi = new VersionInfo (srcFile, "", false, VersionStatus.Versioned | VersionStatus.ScheduledDelete, rev, VersionStatus.Versioned, null);
					versions.Add (rvi);
					status = VersionStatus.Versioned | VersionStatus.ScheduledAdd;
				}
				else*/

			// Files for which git did not report an status are supposed to be tracked
			foreach (FilePath file in existingFiles) {
				VersionInfo vi = new VersionInfo (file, "", false, VersionStatus.Versioned, rev, VersionStatus.Versioned, null);
				versions.Add (vi);
			}
			
			return versions.ToArray ();
		}
		protected override Revision[] OnGetHistory (FilePath localFile, Revision since)
		{
			var repository = GetRepository (localFile);
			var hc = GetHeadCommit (repository);
			if (hc == null)
				return new GitRevision [0];

			var sinceRev = since != null ? ((GitRevision)since).Commit : null;
			IEnumerable<Commit> commits = repository.Commits;
			if (localFile.CanonicalPath != RootPath.CanonicalPath.ResolveLinks ()) {
				var localPath = repository.ToGitPath (localFile);
				commits = commits.Where (c => {
					int count = c.Parents.Count ();
					if (count > 1)
						return false;

					var localTreeEntry = c.Tree [localPath];
					if (localTreeEntry == null)
						return false;

					if (count == 0)
						return true;

					var parentTreeEntry = c.Parents.Single ().Tree [localPath];
					return parentTreeEntry == null || localTreeEntry.Target.Id != parentTreeEntry.Target.Id;
				});
			}

			return commits.TakeWhile (c => c != sinceRev).Select (commit => {
				var author = commit.Author;
				var rev = new GitRevision (this, repository, commit, author.When.LocalDateTime, author.Name, commit.Message) {
					Email = author.Email,
					ShortMessage = commit.MessageShort,
					FileForChanges = localFile,
				};
				return rev;
			}).ToArray ();
		}
		public override VersionInfo GetVersionInfo (FilePath localPath, bool getRemoteStatus)
		{
			if (Directory.Exists (localPath)) {
				GitRevision rev = new GitRevision (this, "");
				return new VersionInfo (localPath, "", true, VersionStatus.Versioned, rev, VersionStatus.Versioned, null);
			}
			else {
				VersionInfo[] infos = GetDirectoryVersionInfo (localPath.ParentDirectory, localPath.FileName, getRemoteStatus, false);
				if (infos.Length == 1)
					return infos[0];
				else
					return null;
			}
		}
Exemple #8
0
		void GetDirectoryVersionInfoCore (NGit.Repository repository, GitRevision rev, FilePath [] localPaths, HashSet<FilePath> existingFiles, HashSet<FilePath> nonVersionedMissingFiles, List<VersionInfo> versions)
		{
			
			var status = new FilteredStatus (repository, repository.ToGitPath (localPaths)).Call (); 
			HashSet<string> added = new HashSet<string> ();
			Action<IEnumerable<string>, VersionStatus> AddFiles = delegate(IEnumerable<string> files, VersionStatus fstatus) {
				foreach (string file in files) {
					if (!added.Add (file))
						continue;
					FilePath statFile = repository.FromGitPath (file);
					existingFiles.Remove (statFile.CanonicalPath);
					nonVersionedMissingFiles.Remove (statFile.CanonicalPath);
					versions.Add (new VersionInfo (statFile, "", false, fstatus, rev, VersionStatus.Versioned, null));
				}
			};
			
			AddFiles (status.GetAdded (), VersionStatus.Versioned | VersionStatus.ScheduledAdd);
			AddFiles (status.GetChanged (), VersionStatus.Versioned | VersionStatus.Modified);
			AddFiles (status.GetModified (), VersionStatus.Versioned | VersionStatus.Modified);
			AddFiles (status.GetRemoved (), VersionStatus.Versioned | VersionStatus.ScheduledDelete);
			AddFiles (status.GetMissing (), VersionStatus.Versioned | VersionStatus.ScheduledDelete);
			AddFiles (status.GetConflicting (), VersionStatus.Versioned | VersionStatus.Conflicted);
			AddFiles (status.GetUntracked (), VersionStatus.Unversioned);
		}
		static void GetDirectoryVersionInfoCore (LibGit2Sharp.Repository repo, GitRevision rev, FilePath directory, List<VersionInfo> versions, bool recursive)
		{
			var relativePath = repo.ToGitPath (directory);
			var status = repo.RetrieveStatus (new StatusOptions {
				PathSpec = relativePath != "." ? new [] { relativePath } : null,
				IncludeUnaltered = true,
			});

			foreach (var statusEntry in status) {
				AddStatus (repo, rev, statusEntry.FilePath, versions, statusEntry.State, recursive ? null : directory);
			}
		}
		VersionInfo[] GetDirectoryVersionInfo (FilePath localDirectory, IEnumerable<FilePath> localFileNames, bool getRemoteStatus, bool recursive)
		{
			List<VersionInfo> versions = new List<VersionInfo> ();
			HashSet<FilePath> existingFiles = new HashSet<FilePath> ();
			HashSet<FilePath> nonVersionedMissingFiles = new HashSet<FilePath> ();
			
			if (localFileNames != null) {
				var localFiles = new List<FilePath> ();
				var arev = new GitRevision (this, "");
				foreach (var p in localFileNames) {
					if (Directory.Exists (p)) {
						if (recursive)
							versions.AddRange (GetDirectoryVersionInfo (p, getRemoteStatus, true));
						else
							versions.Add (new VersionInfo (p, "", true, VersionStatus.Versioned, arev, VersionStatus.Versioned, null));
					}
					else {
						localFiles.Add (p);
						if (File.Exists (p))
							existingFiles.Add (p.CanonicalPath);
						else
							nonVersionedMissingFiles.Add (p.CanonicalPath);
					}
				}
				// No files to check, we are done
				if (localFiles.Count == 0)
					return versions.ToArray ();
				
				localFileNames = localFiles;
			} else {
				CollectFiles (existingFiles, localDirectory, recursive);
			}
			
			GitRevision rev;
			var headCommit = GetHeadCommit ();
			if (headCommit != null)
				rev = new GitRevision (this, headCommit.Id.Name);
			else
				rev = null;
			
			IEnumerable<string> paths;
			if (localFileNames == null) {
				if (recursive)
					paths = new [] { (string) localDirectory };
				else
					paths = Directory.GetFiles (localDirectory);
			} else {
				paths = localFileNames.Select (f => (string)f);
			}
			paths = paths.Select (f => ToGitPath (f));

			var status = new FilteredStatus (repo, paths).Call (); 
			HashSet<string> added = new HashSet<string> ();
			Action<IEnumerable<string>, VersionStatus> AddFiles = delegate(IEnumerable<string> files, VersionStatus fstatus) {
				foreach (string file in files) {
					if (!added.Add (file))
						continue;
					FilePath statFile = FromGitPath (file);
					existingFiles.Remove (statFile.CanonicalPath);
					nonVersionedMissingFiles.Remove (statFile.CanonicalPath);
					versions.Add (new VersionInfo (statFile, "", false, fstatus, rev, VersionStatus.Versioned, null));
				}
			};
			
			AddFiles (status.GetAdded (), VersionStatus.Versioned | VersionStatus.ScheduledAdd);
			AddFiles (status.GetChanged (), VersionStatus.Versioned | VersionStatus.Modified);
			AddFiles (status.GetModified (), VersionStatus.Versioned | VersionStatus.Modified);
			AddFiles (status.GetRemoved (), VersionStatus.Versioned | VersionStatus.ScheduledDelete);
			AddFiles (status.GetMissing (), VersionStatus.Versioned | VersionStatus.ScheduledDelete);
			AddFiles (status.GetConflicting (), VersionStatus.Versioned | VersionStatus.Conflicted);
			AddFiles (status.GetUntracked (), VersionStatus.Unversioned);

			// Existing files for which git did not report an status are supposed to be tracked
			foreach (FilePath file in existingFiles) {
				VersionInfo vi = new VersionInfo (file, "", false, VersionStatus.Versioned, rev, VersionStatus.Versioned, null);
				versions.Add (vi);
			}
			
			// Non existing files for which git did not report an status are unversioned
			foreach (FilePath file in nonVersionedMissingFiles)
				versions.Add (VersionInfo.CreateUnversioned (file, false));
			
			return versions.ToArray ();
		}
		static void AddStatus (LibGit2Sharp.Repository repo, GitRevision rev, string file, List<VersionInfo> versions, FileStatus status, string directoryPath)
		{
			VersionStatus fstatus = VersionStatus.Versioned;

			if (status != FileStatus.Unaltered) {
				if ((status & FileStatus.NewInIndex) != 0)
					fstatus |= VersionStatus.ScheduledAdd;
				else if ((status & (FileStatus.DeletedFromIndex | FileStatus.DeletedFromWorkdir)) != 0)
					fstatus |= VersionStatus.ScheduledDelete;
				else if ((status & (FileStatus.TypeChangeInWorkdir | FileStatus.ModifiedInWorkdir)) != 0)
					fstatus |= VersionStatus.Modified;
				else if ((status & (FileStatus.RenamedInIndex | FileStatus.RenamedInWorkdir)) != 0)
					fstatus |= VersionStatus.ScheduledReplace;
				else if ((status & (FileStatus.Nonexistent | FileStatus.NewInWorkdir)) != 0)
					fstatus = VersionStatus.Unversioned;
				else if ((status & FileStatus.Ignored) != 0)
					fstatus = VersionStatus.Ignored;
			}

			if (repo.Index.Conflicts [file] != null)
				fstatus = VersionStatus.Versioned | VersionStatus.Conflicted;

			var versionPath = repo.FromGitPath (file);
			if (directoryPath != null && versionPath.ParentDirectory != directoryPath) {
				return;
			}

			versions.Add (new VersionInfo (versionPath, "", false, fstatus, rev, fstatus == VersionStatus.Ignored ? VersionStatus.Unversioned : VersionStatus.Versioned, null));
		}
		static void GetFilesVersionInfoCore (LibGit2Sharp.Repository repo, GitRevision rev, List<FilePath> localPaths, List<VersionInfo> versions)
		{
			foreach (var file in repo.ToGitPath (localPaths)) {
				var status = repo.RetrieveStatus (file);
				AddStatus (repo, rev, file, versions, status, null);
			}
		}
		protected override Revision[] OnGetHistory (FilePath localFile, Revision since)
		{
			var revs = new List<Revision> ();

			var repository = GetRepository (localFile);
			var hc = GetHeadCommit (repository);
			if (hc == null)
				return new GitRevision [0];

			var sinceRev = since != null ? ((GitRevision)since).Commit : null;
			IEnumerable<Commit> commits = repository.Commits;
			if (localFile.CanonicalPath != RootPath.CanonicalPath.ResolveLinks ()) {
				var localPath = repository.ToGitPath (localFile);
				commits = commits.Where (c => c.Parents.Count () == 1 && c.Tree [localPath] != null &&
					(c.Parents.FirstOrDefault ().Tree [localPath] == null ||
					c.Tree [localPath].Target.Id != c.Parents.FirstOrDefault ().Tree [localPath].Target.Id));
			}

			foreach (var commit in commits.TakeWhile (c => c != sinceRev)) {
				var author = commit.Author;
				var rev = new GitRevision (this, repository, commit, author.When.LocalDateTime, author.Name, commit.Message) {
					Email = author.Email,
					ShortMessage = commit.MessageShort,
					FileForChanges = localFile,
				};
				revs.Add (rev);
			}

			return revs.ToArray ();
		}
Exemple #14
0
		public override Revision[] GetHistory (FilePath localFile, Revision since)
		{
			List<Revision> revs = new List<Revision> ();
		
			var repository = GetRepository (localFile);
			var hc = GetHeadCommit (repository);
			if (hc == null)
				return new GitRevision [0];

			RevWalk walk = new RevWalk (repository);
			string path = repository.ToGitPath (localFile);
			if (path != ".")
				walk.SetTreeFilter (FollowFilter.Create (path));
			walk.MarkStart (hc);
			
			foreach (RevCommit commit in walk) {
				PersonIdent author = commit.GetAuthorIdent ();
				GitRevision rev = new GitRevision (this, repository, commit.Id.Name, author.GetWhen().ToLocalTime (), author.GetName (), commit.GetFullMessage ());
				rev.Email = author.GetEmailAddress ();
				rev.ShortMessage = commit.GetShortMessage ();
				rev.Commit = commit;
				rev.FileForChanges = localFile;
				revs.Add (rev);
			}
			return revs.ToArray ();
		}
		VersionInfo[] GetDirectoryVersionInfo (FilePath localDirectory, string fileName, bool getRemoteStatus, bool recursive)
		{
			StringReader sr = RunCommand ("log -1 --format=format:%H", true);
			string strRev = sr.ReadLine ();
			sr.Close ();
			
			HashSet<FilePath> existingFiles = new HashSet<FilePath> ();
			if (fileName != null) {
				FilePath fp = localDirectory.Combine (fileName).CanonicalPath;
				if (File.Exists (fp))
					existingFiles.Add (fp);
			} else
				CollectFiles (existingFiles, localDirectory, recursive);
			
			GitRevision rev = new GitRevision (this, strRev);
			List<VersionInfo> versions = new List<VersionInfo> ();
			FilePath p = fileName != null ? localDirectory.Combine (fileName) : localDirectory;
			sr = RunCommand ("status -s " + ToCmdPath (p), true);
			string line;
			while ((line = sr.ReadLine ()) != null) {
				char staged = line[0];
				char nostaged = line[1];
				string file = line.Substring (3);
				FilePath srcFile = FilePath.Null;
				int i = file.IndexOf ("->");
				if (i != -1) {
					srcFile = path.Combine (file.Substring (0, i - 1));
					file = file.Substring (i + 3);
				}
				FilePath statFile = path.Combine (file);
				if (statFile.ParentDirectory != localDirectory && (!statFile.IsChildPathOf (localDirectory) || !recursive))
					continue;
				VersionStatus status;
				if (staged == 'M' || nostaged == 'M')
					status = VersionStatus.Versioned | VersionStatus.Modified;
				else if (staged == 'A')
					status = VersionStatus.Versioned | VersionStatus.ScheduledAdd;
				else if (staged == 'D' || nostaged == 'D')
					status = VersionStatus.Versioned | VersionStatus.ScheduledDelete;
				else if (staged == 'U' || nostaged == 'U')
					status = VersionStatus.Versioned | VersionStatus.Conflicted;
				else if (staged == 'R') {
					// Renamed files are in reality files delete+added to a different location.
					existingFiles.Remove (srcFile.CanonicalPath);
					VersionInfo rvi = new VersionInfo (srcFile, "", false, VersionStatus.Versioned | VersionStatus.ScheduledDelete, rev, VersionStatus.Versioned, null);
					versions.Add (rvi);
					status = VersionStatus.Versioned | VersionStatus.ScheduledAdd;
				}
				else
					status = VersionStatus.Unversioned;
				
				existingFiles.Remove (statFile.CanonicalPath);
				VersionInfo vi = new VersionInfo (statFile, "", false, status, rev, VersionStatus.Versioned, null);
				versions.Add (vi);
			}
			
			// Files for which git did not report an status are supposed to be tracked
			foreach (FilePath file in existingFiles) {
				VersionInfo vi = new VersionInfo (file, "", false, VersionStatus.Versioned, rev, VersionStatus.Versioned, null);
				versions.Add (vi);
			}
			
			return versions.ToArray ();
		}
Exemple #16
0
		VersionInfo[] GetDirectoryVersionInfo (FilePath localDirectory, IEnumerable<FilePath> localFileNames, bool getRemoteStatus, bool recursive)
		{
			List<VersionInfo> versions = new List<VersionInfo> ();
			HashSet<FilePath> existingFiles = new HashSet<FilePath> ();
			HashSet<FilePath> nonVersionedMissingFiles = new HashSet<FilePath> ();
			
			if (localFileNames != null) {
				var localFiles = new List<FilePath> ();
				foreach (var group in GroupByRepository (localFileNames)) {
					var repository = group.Key;
					var arev = new GitRevision (this, repository, "");
					foreach (var p in group) {
						if (Directory.Exists (p)) {
							if (recursive)
								versions.AddRange (GetDirectoryVersionInfo (p, getRemoteStatus, true));
							else
								versions.Add (new VersionInfo (p, "", true, VersionStatus.Versioned, arev, VersionStatus.Versioned, null));
						}
						else {
							localFiles.Add (p);
							if (File.Exists (p))
								existingFiles.Add (p.CanonicalPath);
							else
								nonVersionedMissingFiles.Add (p.CanonicalPath);
						}
					}
				}
				// No files to check, we are done
				if (localFiles.Count == 0)
					return versions.ToArray ();
				
				localFileNames = localFiles;
			} else {
				CollectFiles (existingFiles, localDirectory, recursive);
			}

			IEnumerable<FilePath> paths;
			if (localFileNames == null) {
				if (recursive) {
					paths = new [] { localDirectory };
				} else {
					paths = Directory.GetFiles (localDirectory).Select (f => (FilePath)f).ToArray ();
				}
			} else {
				paths = localFileNames.Select (f => f).ToArray ();
			}

			foreach (var group in paths.GroupBy (p => GetRepository (p))) {
				var repository = group.Key;
				var files = group.ToArray ();
				
				GitRevision rev;
				var headCommit = GetHeadCommit (repository);
				if (headCommit != null)
					rev = new GitRevision (this, repository, headCommit.Id.Name);
				else
					rev = null;

				GetDirectoryVersionInfoCore (repository, rev, files.ToArray (), existingFiles, nonVersionedMissingFiles, versions);
				
				// Existing files for which git did not report an status are supposed to be tracked
				foreach (FilePath file in existingFiles.Where (f => files.Contains (f))) {
					VersionInfo vi = new VersionInfo (file, "", false, VersionStatus.Versioned, rev, VersionStatus.Versioned, null);
					versions.Add (vi);
				}
			}


			// Non existing files for which git did not report an status are unversioned
			foreach (FilePath file in nonVersionedMissingFiles)
				versions.Add (VersionInfo.CreateUnversioned (file, false));

			return versions.ToArray ();
		}
		internal GitRevision GetPreviousRevisionFor (GitRevision revision)
		{
			StringReader sr = RunCommand ("log -1 --name-status --date=iso " + revision + "^", true);
			string rev = ReadWithPrefix (sr, "commit ");
			string author = ReadWithPrefix  (sr, "Author: ");
			string dateStr = ReadWithPrefix (sr, "Date:   ");
			DateTime date;
			DateTime.TryParse (dateStr, out date);
			
			List<RevisionPath> paths = new List<RevisionPath> ();
			bool readingComment = true;
			StringBuilder message = new StringBuilder ();
			StringBuilder interline = new StringBuilder ();
			
			string line;
			while ((line = sr.ReadLine ()) != null) {
				if (line.Length > 2 && ("ADM".IndexOf (line[0]) != -1) && line [1] == '\t') {
					readingComment = false;
					string file = line.Substring (2);
					RevisionAction ra;
					switch (line[0]) {
					case 'A': ra = RevisionAction.Add; break;
					case 'D': ra = RevisionAction.Delete; break;
					default: ra = RevisionAction.Modify; break;
					}
					RevisionPath p = new RevisionPath (path.Combine (file), ra, null);
					paths.Add (p);
				}
				else if (readingComment) {
					if (IsEmptyLine (line))
						interline.AppendLine (line);
					else {
						message.Append (interline);
						message.AppendLine (line);
						interline = new StringBuilder ();
					}
				}
				else
					break;
			}
			
			return new GitRevision (this, rev, date, author, message.ToString ().Trim ('\n','\r'), paths.ToArray ());
		}
		protected override Revision GetHeadRevision ()
		{
			GitRepository repo2 = (GitRepository)repo;
			RevWalk rw = new RevWalk (repo2.RootRepository);
			ObjectId headId = repo2.RootRepository.Resolve (Constants.HEAD);
			if (headId == null)
				return null;

			RevCommit commit = rw.ParseCommit (headId);
			GitRevision rev = new GitRevision (repo, repo2.RootRepository, commit.Id.Name);
			rev.Commit = commit;
			return rev;
		}
		public override Revision[] GetHistory (FilePath localFile, Revision since)
		{
			List<Revision> revs = new List<Revision> ();
			
			RevWalk walk = new RevWalk (repo);
			var hc = GetHeadCommit ();
			if (hc == null)
				return new GitRevision [0];
			walk.MarkStart (hc);
			
			foreach (RevCommit commit in walk) {
				List<RevisionPath> paths = new List<RevisionPath> ();
				foreach (Change change in GitUtil.GetCommitChanges (repo, commit)) {
					FilePath cpath = FromGitPath (change.Path);
					if (cpath != localFile && !cpath.IsChildPathOf (localFile))
						continue;
					RevisionAction ra;
					switch (change.ChangeType) {
					case ChangeType.Added:
						ra = RevisionAction.Add;
						break;
					case ChangeType.Deleted:
						ra = RevisionAction.Delete;
						break;
					default:
						ra = RevisionAction.Modify;
						break;
					}
					RevisionPath p = new RevisionPath (cpath, ra, null);
					paths.Add (p);
				}
				if (paths.Count > 0) {
					PersonIdent author = commit.GetAuthorIdent ();
					GitRevision rev = new GitRevision (this, commit.Id.Name, author.GetWhen().ToLocalTime (), author.GetName (), commit.GetFullMessage (), paths.ToArray ());
					rev.Email = author.GetEmailAddress ();
					rev.ShortMessage = commit.GetShortMessage ();
					revs.Add (rev);
				}
			}
			return revs.ToArray ();
		}