Beispiel #1
0
        // GET: /<controller>/
        public async Task <IActionResult> Raw([FromServices] IContentProvider contentProvider, string path)
        {
            var cp       = ContentPath.FromUrlPath(path);
            var content  = contentProvider.Read(cp);
            var mimeType = cp.Name.Select(MimeTypes.GetMimeType).ValueOr(MimeTypes.FallbackMimeType);

            return(File(content.Value, mimeType));
        }
Beispiel #2
0
        public async Task <IViewComponentResult> InvokeAsync(ContentPath path)
        {
            var parts = path.Lineage.Select(_ => new Link {
                Name = _.GetDisplayName("Home"), Href = _.VirtualPath
            });

            return(View(parts));
        }
Beispiel #3
0
        static Option <string> GetDirectoryReadme(IContentProvider provider, ContentPath path)
        {
            var candidates = new[] { "Readme.md", "Index.md" };
            var markdown   = candidates
                             .Select(_ => GetText(provider, path.CatDir(_)))
                             .FirstOrNone();

            return(markdown);
        }
Beispiel #4
0
 static Option <string> GetText(IContentProvider provider, ContentPath path)
 {
     return(provider.Read(path).Select(_ =>
     {
         using (var r = new StreamReader(_))
         {
             return r.ReadToEnd();
         }
     }));
 }
Beispiel #5
0
        internal static GrepResult ParseGitGrepOutputLine(string line)
        {
            var p = line.Split(":", 3);

            return(new GrepResult
            {
                Path = ContentPath.FromUrlPath(p[0]),
                LineNumber = Int32.Parse(p[1]),
                Text = p[2]
            });
        }
Beispiel #6
0
 static Option <string> GetChildList(ContentPath directory, IEnumerable <ContentPath> children)
 {
     if (children.Any())
     {
         return(String.Join(String.Empty, children.Select(_ => $"* [{_.Name.ValueOr(_.ToString())}]({_.AbsoluteHref})\r\n")));
     }
     else
     {
         return(Option.None);
     }
 }
Beispiel #7
0
        internal static ContentPath FromUrlPath(string path)
        {
            if (String.IsNullOrEmpty(path))
            {
                return(ContentPath.Root);
            }

            var cp = new ContentPath(path.Split(separator, StringSplitOptions.RemoveEmptyEntries)
                                     .Select(WebUtility.UrlDecode));

            return(cp);
        }
Beispiel #8
0
        public async Task <IActionResult> Grep(
            [FromServices] IContentProvider contentProvider,
            [FromServices] IProcessRunner runner,
            [FromServices] IMarkdownRenderer renderer,
            [FromServices] IContentGrep grep,
            [FromQuery] string q)
        {
            var result = await grep.Grep(q);

            var markdown = result.Select(_ => $"* [{_.Path}]({_.Path.AbsoluteHref}#{_.LineNumber})({_.LineNumber}): `{_.Text.Truncate(256)}`").JoinLines();

            return(await MarkdownView(renderer, ContentPath.FromUrlPath("/"), markdown));
        }
        public Option <Stream> Read(ContentPath path)
        {
            var fsPath = path.GetFileSystemPath(rootDirectory);

            if (File.Exists(fsPath))
            {
                return(File.OpenRead(fsPath));
            }
            else
            {
                return(Option.None);
            }
        }
Beispiel #10
0
        static bool IsText(IContentProvider contentProvider, ContentPath contentPath)
        {
            var reader = contentProvider.Read(contentPath);

            if (!reader.HasValue)
            {
                return(true);
            }
            using (var r = reader.Value)
            {
                var b = Read(r, 4096);
                return(!b.Any(_ => _ == 0) && b.Any(_ => _ == '\n'));
            }
        }
        public IDisposable NotifyChange(ContentPath contentPath, Action <ContentPath> onChanged)
        {
            var fsPath           = this.GetFileSystemPath(contentPath);
            var directoryToWatch = fsPath = (Directory.Exists(fsPath)) ? fsPath : Path.GetDirectoryName(fsPath);
            var w = new FileSystemWatcher(directoryToWatch);

            w.BeginInit();
            FileSystemEventHandler changed = (s, e) =>
            {
                onChanged(contentPath);
            };

            w.Changed += changed;
            w.EndInit();
            w.EnableRaisingEvents = true;
            return(w);
        }
        public IEnumerable <ContentPath> GetChildren(ContentPath path)
        {
            var fsPath = GetFileSystemPath(path);

            if (Directory.Exists(fsPath))
            {
                var c = new DirectoryInfo(fsPath).GetFileSystemInfos()
                        .OrderByDescending(_ => _ is DirectoryInfo).ThenBy(_ => _.Name)
                        .Where(_ => !_.Name.Equals(".git"))
                        .Select(_ => GetChildPath(path, _))
                        .ToList();
                return(c);
            }
            else
            {
                return(Enumerable.Empty <ContentPath>());
            }
        }
        public bool Exists(ContentPath path)
        {
            var fsPath = GetFileSystemPath(path);

            return(File.Exists(fsPath) || Directory.Exists(fsPath));
        }
 static ContentPath GetChildPath(ContentPath p, FileSystemInfo c)
 {
     return(p.CatDir(c.Name));
 }
 string GetFileSystemPath(ContentPath path)
 {
     return(path.GetFileSystemPath(rootDirectory));
 }
Beispiel #16
0
        async Task <IActionResult> MarkdownView(IMarkdownRenderer renderer, ContentPath path, Option <string> markdown)
        {
            var result = await renderer.Render(markdown.ValueOr("empty"));

            return(View("Index", new ContentModel(path, result.Title.ValueOr(path.GetDisplayName("Home")), result.Body)));
        }
Beispiel #17
0
 public static Task <RendererResult> Render(this IRenderer renderer, ContentPath path, string content)
 {
     return(renderer.Render(path, new MemoryStream(System.Text.Encoding.UTF8.GetBytes(content))));
 }
Beispiel #18
0
 public bool IsAncestorOrSelf(ContentPath child)
 {
     return(parts.SequenceEqual(child.parts.Take(parts.Length)));
 }
Beispiel #19
0
        public async Task <Option <string> > GetRecentChanges(ContentPath path)
        {
            var r = await git.Run(new[] { "log", "-100", $"--pretty=format:* [%ar: %s]({path.AbsoluteHref}?log=--stat+-p+-1+-U+%H), by %an", "--", git.GetPath(path) });

            return(r.Success ? UrlEncode(r.Output) : Option <string> .None);
        }
Beispiel #20
0
        public async Task <IActionResult> Stats(
            [FromServices] IMarkdownRenderer renderer,
            [FromServices] IGit git,
            [FromQuery] string q,
            [FromQuery] string since,
            [FromQuery] string until,
            [FromQuery] string author
            )
        {
            var logArgs = Utils.SplitArguments(q).Concat(new[]
            {
                Param(nameof(since), since),
                Param(nameof(until), until),
                Param(nameof(author), author)
            }.WhereValue()).ToArray();

            var c = git.GetChanges(logArgs);

            var byName = c.GroupBy(_ => _.Commit.author.Email)
                         .Select(_ => new
            {
                User         = _.Key,
                AddedLines   = _.Sum(_c => _c.Stats.AddedLines),
                RemovedLines = _.Sum(_c => _c.Stats.RemovedLines)
            })
                         .OrderByDescending(_ => _.AddedLines + _.RemovedLines)
                         .ToList();

            var byPath = c
                         .SelectMany(_ => ContentPath.FromUrlPath(_.Stats.Path).Lineage
                                     .Select(dir => new { Path = dir, Change = _ }))
                         .GroupBy(_ => _.Path)
                         .Select(_ => new
            {
                Path         = _.Key,
                AddedLines   = _.Sum(_c => _c.Change.Stats.AddedLines),
                RemovedLines = _.Sum(_c => _c.Change.Stats.RemovedLines)
            })
                         .OrderByDescending(_ => _.AddedLines)
                         .Take(100)
                         .ToList();

            var markdown = $@"
<form action=""/stats"" method=""get"" >
<input name=""since"" placeholder=""since yyyy-mm-dd"" value={Attribute(since)} />
<input name=""until"" placeholder=""until yyyy-mm-dd"" value={Attribute(until)} />
<input name=""author"" placeholder=""author"" value={Attribute(author)} />
<input type=""submit"" />
</form>

## By User

{byName.MarkdownTable()
    .With("User", _ => $"[{_.User}](/stats?author={_.User})")
    .With("Added Lines", _ => _.AddedLines)
    .With("Removed Lines", _ => _.RemovedLines)
}

## By Path

{byPath.MarkdownTable()
    .With("Path", _ => $"[{_.Path}](/{_.Path})")
    .With("Added Lines", _ => _.AddedLines)
    .With("Removed Lines", _ => _.RemovedLines)
}

";

            return(await MarkdownView(renderer, new ContentPath(), markdown));
        }
Beispiel #21
0
        private static async Task NotifyContentChanged(Microsoft.AspNetCore.Http.WebSocketManager webSockets, IContentProvider contentProvider, ContentPath contentPath)
        {
            var webSocket = await webSockets.AcceptWebSocketAsync();

            using (contentProvider.NotifyChange(contentPath, cp => {
                webSocket.SendAsync(UTF8Encoding.UTF8.GetBytes(cp.ToString()), WebSocketMessageType.Text, true, CancellationToken.None);
            }))
            {
                await WaitForClose(webSocket);
            }
        }
Beispiel #22
0
 public static bool IsImage(this ContentPath cp)
 {
     return(cp.IsExtension(new[] { ".png", ".svg", ".jpg", ".jpeg" }));
 }
Beispiel #23
0
        Option <string> GetSourceAsMarkdown(IContentProvider contentProvider, IHistory history, ContentPath path)
        {
            return(string.Join(hr, new[]
            {
                GetText(contentProvider, path).Select(_ => $@"```{path.ExtensionWithoutDot.ValueOr(String.Empty)}
{_}
```"
                                                      ),
                history.GetRecentChanges(path).Result
            }.WhereValue()));
        }
Beispiel #24
0
 static string GetMarkdown(IContentProvider content, IHistory history, ContentPath path)
 {
     return(String.Join(hr, new[] { GetText(content, path), history.GetRecentChanges(path).Result }.WhereValue()));
 }
Beispiel #25
0
 static string GetDirectoryMarkdown(IContentProvider provider, IHistory history, ContentPath path, IEnumerable <ContentPath> children)
 {
     return(String.Join(hr, new[]
     {
         GetChildList(path, children),
         GetDirectoryReadme(provider, path),
         history.GetRecentChanges(path).Result
     }.WhereValue()));
 }
Beispiel #26
0
 public static string GetPath(this IGit git, ContentPath path)
 {
     return(path.IsRoot
         ? "."
         : String.Join("/", path.Parts));
 }
Beispiel #27
0
        // GET: /<controller>/
        public async Task <IActionResult> Index(
            [FromServices] IContentProvider contentProvider,
            [FromServices] IMarkdownRenderer renderer,
            [FromServices] IHistory history,
            [FromServices] IGit git,
            [FromQuery] string log,
            [FromQuery] string q,
            string path)
        {
            var contentPath = ContentPath.FromUrlPath(path);

            if (this.HttpContext.WebSockets.IsWebSocketRequest)
            {
                await NotifyContentChanged(this.HttpContext.WebSockets, contentProvider, contentPath);

                return(Ok());
            }

            if (log != null)
            {
                var r = await git.Run(new[] { "log" }.Concat(Utils.SplitArguments(log)).Concat(new[] { "--", git.GetPath(contentPath) }));

                return(await MarkdownView(renderer, contentPath, AsCode(r.Output)));
            }

            if (q != null)
            {
                var pretty  = $"--pretty=format:* [%ar: %s]({git.GetPath(contentPath)}?log=--stat+-p+-1+-U+%H), by %an";
                var grepLog = await git.Run(new[] { "log", pretty, "-100", "-S", q, git.GetPath(contentPath) });

                var grepText = git.GrepOutputToMarkdown((await git.Run(new[] { "grep", "-I", "-n", q })).Output);
                return(await MarkdownView(renderer, contentPath, grepLog.Output + hr + grepText));
            }

            var children = contentProvider.GetChildren(contentPath);

            if (children.Any())
            {
                if (!this.HttpContext.Request.Path.Value.EndsWith("/"))
                {
                    var url        = Microsoft.AspNetCore.Http.Extensions.UriHelper.GetEncodedUrl(this.HttpContext.Request);
                    var redirectTo = url + "/";
                    return(this.Redirect(redirectTo));
                }
                return(await MarkdownView(renderer, contentPath, GetDirectoryMarkdown(contentProvider, history, contentPath, children)));
            }

            if (contentPath.IsExtension(new[] { ".md" }))
            {
                return(await MarkdownView(renderer, contentPath, GetMarkdown(contentProvider, history, contentPath)));
            }

            var mdFile = contentPath.CatName(".md");

            if (mdFile.HasValue && contentProvider.Exists(mdFile.Value))
            {
                return(await MarkdownView(renderer, contentPath, GetText(contentProvider, mdFile.Value)));
            }

            if (IsText(contentProvider, contentPath))
            {
                return(await MarkdownView(renderer, contentPath, GetSourceAsMarkdown(contentProvider, history, contentPath)));
            }

            contentProvider.Pull();

            // raw file
            return(await Raw(contentProvider, path));
        }