public IEnumerable <SearchResult> Search(SearchQuery query, FileManager fileManager) { var repos = from dir in fileManager.DirectoryInfo.EnumerateDirectories() let repoInfo = GitUtilities.GetRepoInfo(dir.FullName) where repoInfo.IsGitRepo select repoInfo; foreach (var repo in repos) { if (query.Terms.All(t => repo.Name.IndexOf(t, StringComparison.OrdinalIgnoreCase) != -1 || repo.Description.IndexOf(t, StringComparison.OrdinalIgnoreCase) != -1)) { yield return(new SearchResult { LinkText = repo.Name, ActionName = "ViewRepo", ControllerName = "Browse", RouteValues = new { repo = repo.Name }, Lines = new List <SearchLine> { new SearchLine { Line = repo.Description }, }, }); } } }
public ActionResult ViewRepo(string repo) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory) { return(HttpNotFound()); } var repoInfo = GitUtilities.GetRepoInfo(resourceInfo.FullPath); if (!repoInfo.IsGitRepo) { return(HttpNotFound()); } AddRepoBreadCrumb(repo); var lastCommit = GitUtilities.GetLogEntries(resourceInfo.FullPath, 1).FirstOrDefault(); ViewBag.RepoInfo = GitUtilities.GetRepoInfo(resourceInfo.FullPath); ViewBag.LastCommit = lastCommit; ViewBag.CurrentTree = lastCommit != null?GitUtilities.GetTreeInfo(resourceInfo.FullPath, "HEAD") : null; ViewBag.Refs = GitUtilities.GetAllRefs(resourceInfo.FullPath); return(View()); }
private IEnumerable <SearchResult> Search(SearchQuery query, RepoInfo repo, bool includeRepoName = false) { var allTerms = string.Join(" --or ", query.Terms.Select(t => "-e " + GitUtilities.Q(t))); var commandResult = GitUtilities.Execute("grep --line-number --fixed-strings --ignore-case --context 3 --null --all-match " + allTerms + " HEAD", repo.RepoPath); var repoResults = commandResult.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); return(from m in repoResults where m != "--" where !m.StartsWith("Binary file") let parts = m.Split('\0') let filePath = parts[0].Split(':')[1] let searchLine = new SearchLine { Line = parts[2], LineNumber = int.Parse(parts[1]), } group searchLine by filePath into g select new SearchResult { LinkText = (includeRepoName ? repo.Name + " " : string.Empty) + "/" + g.Key, ActionName = "ViewBlob", ControllerName = "Browse", RouteValues = new { repo = repo.Name, @object = "HEAD", path = g.Key }, Lines = g.ToList(), }); }
public ActionResult ViewCommit(string repo, string @object) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory) { return(HttpNotFound()); } AddRepoBreadCrumb(repo); this.BreadCrumbs.Append("Browse", "ViewCommit", @object, new { repo, @object }); var commit = GitUtilities.GetLogEntries(resourceInfo.FullPath, 1, 0, @object).FirstOrDefault(); if (commit == null) { return(HttpNotFound()); } var diffs = GitUtilities.GetDiffInfo(resourceInfo.FullPath, commit.Parents.FirstOrDefault() ?? GitUtilities.EmptyTreeHash, commit.CommitHash); ViewBag.RepoName = resourceInfo.Name; ViewBag.CommitLogEntry = commit; return(View(diffs)); }
public ActionResult GetInfoRefs(string url) { var service = this.GetService(); var resourceInfo = this.FileManager.GetResourceInfo(url); if (resourceInfo.Type != ResourceType.Directory) { var repoPath = ((FileInfo)resourceInfo.FileSystemInfo).Directory.Parent.FullName; GitUtilities.UpdateServerInfo(repoPath); if (resourceInfo.Type == ResourceType.NotFound) { resourceInfo = this.FileManager.GetResourceInfo(url); } } if (service == null || resourceInfo.Type == ResourceType.Directory) { return(this.Fetch(url)); } else { var repoPath = ((FileInfo)resourceInfo.FileSystemInfo).Directory.Parent.FullName; return(new GitCommandResult("{0} --stateless-rpc --advertise-refs .", service, repoPath)); } }
public ActionResult ViewTree(string repo, string @object, string path) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory) { return(HttpNotFound()); } TreeView items; try { items = GitUtilities.GetTreeInfo(resourceInfo.FullPath, @object, path); } catch (GitErrorException) { return(HttpNotFound()); } AddRepoBreadCrumb(repo); this.BreadCrumbs.Append("Browse", "ViewTree", @object, new { repo, @object, path = string.Empty }); this.BreadCrumbs.Append("Browse", "ViewTree", BreadCrumbTrail.EnumeratePath(path), p => p.Key, p => new { repo, @object, path = p.Value }); ViewBag.RepoName = resourceInfo.Name; ViewBag.Tree = @object; ViewBag.Path = path ?? string.Empty; return(View(items)); }
public ActionResult ViewGraph(string repo, int page = 1) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory || page < 1) { return(HttpNotFound()); } const int PageSize = 50; int skip = PageSize * (page - 1); var count = GitUtilities.CountCommits(resourceInfo.FullPath, allRefs: true); if (skip >= count) { return(HttpNotFound()); } this.BreadCrumbs.Append("Browse", "Index", "Browse"); AddRepoBreadCrumb(repo); this.BreadCrumbs.Append("Graph", "ViewGraph", "View Graph", new { repo }); var commits = GetLogEntries(resourceInfo.FullPath, skip + PageSize).Skip(skip).ToList(); ViewBag.PaginationInfo = new PaginationInfo(page, (count + PageSize - 1) / PageSize, "Graph", "ViewGraph", new { repo }); ViewBag.RepoName = resourceInfo.Name; return(View(commits)); }
public ActionResult ManageRepo(string repoName, RepoSettings settings) { var resourceInfo = this.FileManager.GetResourceInfo(repoName); if (resourceInfo.Type != ResourceType.Directory) { return(HttpNotFound()); } var repo = GitUtilities.GetRepoInfo(resourceInfo.FullPath); if (!repo.IsGitRepo) { return(HttpNotFound()); } if (!ModelState.IsValid) { return(View(settings)); } io::File.WriteAllText(Path.Combine(resourceInfo.FullPath, "description"), settings.Description); if (repo.IsArchived != settings.IsArchived) { GitUtilities.ToggleArchived(resourceInfo.FullPath); } return(RedirectToAction("ViewRepo", "Browse", new { repo = repoName })); }
public ActionResult ViewCommits(string repo, string @object = null, int page = 1) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory || page < 1) { return(HttpNotFound()); } const int PageSize = 20; int skip = PageSize * (page - 1); var count = GitUtilities.CountCommits(resourceInfo.FullPath, @object); if (skip >= count) { return(HttpNotFound()); } AddRepoBreadCrumb(repo); this.BreadCrumbs.Append("Browse", "ViewCommits", "Commit Log", new { repo, @object }); var commits = GitUtilities.GetLogEntries(resourceInfo.FullPath, PageSize, skip, @object); var branches = GitUtilities.GetAllRefs(resourceInfo.FullPath).Where(r => r.RefType == RefType.Branch).ToList(); ViewBag.PaginationInfo = new PaginationInfo(page, (count + PageSize - 1) / PageSize, "Browse", "ViewCommits", new { repo }); ViewBag.RepoName = resourceInfo.Name; ViewBag.Object = @object ?? "HEAD"; ViewBag.Branches = branches; return(View(commits)); }
public ActionResult Index(bool archived = false) { var directory = this.FileManager.DirectoryInfo; ViewBag.Archived = archived; var repos = (from dir in directory.EnumerateDirectories() select GitUtilities.GetRepoInfo(dir.FullName)).Where(ri => ri.IsArchived == archived).ToList(); return(View(repos)); }
public IEnumerable <SearchResult> Search(SearchQuery query, FileManager fileManager) { var repos = from dir in fileManager.DirectoryInfo.EnumerateDirectories() let repoInfo = GitUtilities.GetRepoInfo(dir.FullName) where repoInfo.IsGitRepo select repoInfo; return(from repo in repos from searchResult in Search(query, repo, includeRepoName: true) select searchResult); }
public ActionResult LastCommits() { var directory = this.FileManager.DirectoryInfo; var items = from repo in directory.EnumerateDirectories() from entry in GitUtilities.GetLogEntries(repo.FullName, 1) select FormatLogEntry(entry, repo.Name); var feed = BuildFeed("Last Commit in All Repos", items); return(new AtomActionResult(feed)); }
public override void ExecuteResult(ControllerContext context) { var response = context.HttpContext.Response; var commandResult = GitUtilities.Execute(string.Format(this.commandFormat, this.service), this.workingDir); var commandData = GitUtilities.DefaultEncoding.GetBytes(commandResult); response.StatusCode = 200; response.ContentType = "application/x-git-" + this.service + "-advertisement"; response.BinaryWrite(PacketFormat(string.Format("# service=git-{0}\n", this.service))); response.BinaryWrite(PacketFlush()); response.BinaryWrite(commandData); }
public ActionResult Create(CreateRepoRequest request) { string repoPath = null; if (ModelState.IsValid) { var invalid = Path.GetInvalidFileNameChars(); if (request.RepoName.Any(c => invalid.Contains(c))) { ModelState.AddModelError("RepoName", "Repository name must be a valid folder name."); } else { var resourceInfo = this.FileManager.GetResourceInfo(request.RepoName); if (resourceInfo.FileSystemInfo == null) { ModelState.AddModelError("RepoName", "You do not have permission to create this repository."); } if (resourceInfo.Type != ResourceType.NotFound) { ModelState.AddModelError("RepoName", "There is already an object at that location."); } repoPath = resourceInfo.FullPath; } } if (!ModelState.IsValid) { return(View(request)); } try { GitUtilities.CreateRepo(repoPath); } catch (GitErrorException ex) { ModelState.AddModelError(string.Empty, ex.Message); return(View(request)); } io::File.WriteAllText(Path.Combine(repoPath, "description"), request.Description); GitUtilities.ExecutePostCreateHook(repoPath); return(RedirectToAction("ViewRepo", "Browse", new { repo = request.RepoName })); }
public ActionResult Commits(string repo) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory) { return(HttpNotFound()); } var items = from entry in GitUtilities.GetLogEntries(resourceInfo.FullPath, 20) select FormatLogEntry(entry, repo); var feed = BuildFeed(repo + " Commits", items); return(new AtomActionResult(feed)); }
public ActionResult ViewRepoImpact(string repo) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory) { return(HttpNotFound()); } this.BreadCrumbs.Append("Browse", "Index", "Browse"); AddRepoBreadCrumb(repo); this.BreadCrumbs.Append("Impact", "ViewRepoImpact", "Impact", new { repo }); var userImpacts = GitUtilities.GetUserImpacts(resourceInfo.FullPath); var allTimeImpacts = (from g in userImpacts.GroupBy(u => u.Author, StringComparer.InvariantCultureIgnoreCase) select new UserImpact { Author = g.Key, Commits = g.Sum(ui => ui.Commits), Insertions = g.Sum(ui => ui.Insertions), Deletions = g.Sum(ui => ui.Deletions), Impact = g.Sum(ui => ui.Impact), }).OrderByDescending(i => i.Commits); var weeklyImpacts = (from u in userImpacts let dayOffset = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek - u.Date.DayOfWeek let commitWeek = u.Date.Date.AddDays(dayOffset + (dayOffset > 0 ? -7 : 0)) group u by commitWeek into wk select new ImpactWeek { Week = wk.Key, Impacts = (from g in wk.GroupBy(u => u.Author, StringComparer.InvariantCultureIgnoreCase) select new UserImpact { Author = g.Key, Commits = g.Sum(ui => ui.Commits), Insertions = g.Sum(ui => ui.Insertions), Deletions = g.Sum(ui => ui.Deletions), Impact = g.Sum(ui => ui.Impact), }).OrderByDescending(i => i.Commits).ToList() }).OrderBy(wk => wk.Week); ViewBag.AllTime = allTimeImpacts; ViewBag.Weekly = weeklyImpacts; return(View()); }
public ActionResult SearchRepo(string repo, string q) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory) { return(HttpNotFound()); } var repoInfo = GitUtilities.GetRepoInfo(resourceInfo.FullPath); if (!repoInfo.IsGitRepo) { return(HttpNotFound()); } return(Search(q, repoInfo)); }
public ActionResult ManageRepo(string repoName) { var resourceInfo = this.FileManager.GetResourceInfo(repoName); if (resourceInfo.Type != ResourceType.Directory) { return(HttpNotFound()); } var repo = GitUtilities.GetRepoInfo(resourceInfo.FullPath); if (!repo.IsGitRepo) { return(HttpNotFound()); } return(View(new RepoSettings { Description = repo.Description, IsArchived = repo.IsArchived, })); }
public override void ExecuteResult(ControllerContext context) { var response = context.HttpContext.Response; var request = context.HttpContext.Request; response.ContentType = this.contentType; response.AddHeader("Content-disposition", "attachment"); response.Buffer = false; response.BufferOutput = false; using (var git = GitUtilities.StartGetBlob(this.repoPath, this.tree, this.path)) { var writeBuffer = new char[4194304]; int writeCount; while ((writeCount = git.StandardOutput.ReadBlock(writeBuffer, 0, writeBuffer.Length)) > 0) { var bytes = GitUtilities.DefaultEncoding.GetBytes(writeBuffer, 0, writeCount); response.BinaryWrite(bytes); } git.WaitForExit(); } }
public List <GraphEntry> GetLogEntries(string path, int count) { var nodeColors = new Dictionary <string, int>(); var colorNumber = 0; var entries = GitUtilities.GetLogEntries(path, count + 1000, allRefs: true); var refs = GitUtilities.GetAllRefs(path); var results = new List <GraphEntry>(); var incoming = new List <string>(); foreach (var entry in entries.Take(count)) { var color = ColorNode(entry, nodeColors, ref colorNumber); results.Add(new GraphEntry { LogEntry = entry, Refs = refs.Where(r => r.ShaId == entry.CommitHash).ToList(), Node = new NodeInfo { Hash = entry.CommitHash, Color = color }, IncomingNodes = incoming.Select(i => new NodeInfo { Hash = i, Color = nodeColors[i] }).ToList(), ParentNodes = entry.Parents.Select(i => new NodeInfo { Hash = i, Color = nodeColors[i] }).ToList(), }); incoming = BuildOutgoing(incoming, entry); } return(results); }
public override void ExecuteResult(ControllerContext context) { var response = context.HttpContext.Response; var request = context.HttpContext.Request; var realRequest = System.Web.HttpContext.Current.Request; response.ContentType = "application/x-git-" + this.action + "-result"; response.BufferOutput = false; using (var git = GitUtilities.Start(string.Format(this.commandFormat, this.action), this.repoPath, redirectInput: true)) { var readThread = new Thread(() => { var readBuffer = new byte[4096]; int readCount; Stream wrapperStream = null; try { var input = realRequest.GetBufferlessInputStream(disableMaxRequestLength: true); if (request.Headers["Content-Encoding"] == "gzip") { input = wrapperStream = new GZipStream(input, CompressionMode.Decompress); } while ((readCount = input.Read(readBuffer, 0, readBuffer.Length)) > 0) { git.StandardInput.BaseStream.Write(readBuffer, 0, readCount); } } finally { if (wrapperStream != null) { wrapperStream.Dispose(); } } git.StandardInput.Close(); }); readThread.Start(); var writeBuffer = new byte[4096]; int writeCount; byte[] copy = null; while ((writeCount = git.StandardOutput.BaseStream.Read(writeBuffer, 0, writeBuffer.Length)) > 0) { if (copy == null || copy.Length != writeCount) { copy = new byte[writeCount]; } for (int i = 0; i < writeCount; i++) { copy[i] = writeBuffer[i]; } response.BinaryWrite(copy); } readThread.Join(); git.WaitForExit(); } }
public ActionResult ViewBlob(string repo, string @object, string path, bool raw = false) { var resourceInfo = this.FileManager.GetResourceInfo(repo); if (resourceInfo.Type != ResourceType.Directory || string.IsNullOrEmpty(path)) { return(HttpNotFound()); } var fileName = Path.GetFileName(path); var containingPath = path.Substring(0, path.Length - fileName.Length); TreeView items; try { items = GitUtilities.GetTreeInfo(resourceInfo.FullPath, @object, containingPath); } catch (GitErrorException) { return(HttpNotFound()); } if (!items.Objects.Any(o => o.Name == fileName)) { return(HttpNotFound()); } var contentType = MimeUtilities.GetMimeType(fileName); if (raw) { return(new GitFileResult(resourceInfo.FullPath, @object, path, contentType)); } AddRepoBreadCrumb(repo); this.BreadCrumbs.Append("Browse", "ViewTree", @object, new { repo, @object, path = string.Empty }); var paths = BreadCrumbTrail.EnumeratePath(path, TrailingSlashBehavior.LeaveOffLastTrailingSlash).ToList(); this.BreadCrumbs.Append("Browse", "ViewTree", paths.Take(paths.Count() - 1), p => p.Key, p => new { repo, @object, path = p.Value }); this.BreadCrumbs.Append("Browse", "ViewBlob", paths.Last().Key, new { repo, @object, path = paths.Last().Value }); ViewBag.RepoName = resourceInfo.Name; ViewBag.Tree = @object; ViewBag.Path = path; ViewBag.FileName = fileName; ViewBag.ContentType = contentType; string model = null; if (contentType.StartsWith("text/") || contentType == "application/xml" || Regex.IsMatch(contentType, @"^application/.*\+xml$")) { using (var blob = GitUtilities.GetBlob(resourceInfo.FullPath, @object, path)) { using (var reader = new StreamReader(blob, detectEncodingFromByteOrderMarks: true)) { model = reader.ReadToEnd(); } } } return(View((object)model)); }
private IEnumerable <SearchResult> Search(SearchQuery query, RepoInfo repo, bool includeRepoName = false) { TreeView tree; try { tree = GitUtilities.GetTreeInfo(repo.RepoPath, "HEAD", recurse: true); } catch (GitErrorException) { yield break; } foreach (var item in tree.Objects) { var name = item.Name.Substring(item.Name.LastIndexOf('/') + 1); if (query.Terms.All(t => name.IndexOf(t, StringComparison.OrdinalIgnoreCase) != -1)) { var linkText = (includeRepoName ? repo.Name + " " : string.Empty) + "/" + item.Name; switch (item.ObjectType) { case ObjectType.Tree: yield return(new SearchResult { LinkText = linkText + "/", ActionName = "ViewTree", ControllerName = "Browse", RouteValues = new { repo = repo.Name, @object = tree.Tree, path = tree.Path + item.Name + "/" }, Lines = new List <SearchLine>(), }); break; case ObjectType.Blob: yield return(new SearchResult { LinkText = linkText, ActionName = "ViewBlob", ControllerName = "Browse", RouteValues = new { repo = repo.Name, @object = tree.Tree, path = tree.Path + item.Name }, Lines = new List <SearchLine>(), }); break; case ObjectType.Commit: yield return(new SearchResult { LinkText = linkText + "/", ActionName = "ViewTree", ControllerName = "Browse", RouteValues = new { repo = repo.Name, @object = tree.Tree, path = tree.Path + item.Name + "/" }, Lines = new List <SearchLine>(), }); break; } } } }