Added support for GitLab and Bitbucket slideshow presentations.

The GitPitch server has been updated with support for GitPitch slideshow presentations powered by PITCHME.md within GitHub, GitLab and Bitbucket public repos.

The git.repo.services property in application.conf can be used to register and configure custom GRS (Git Repo Services) for any GitPitch server deployment.
This commit is contained in:
David Russell 2016-09-07 14:11:29 +08:00
parent 04fa70d93e
commit f4adfbed3e
38 changed files with 1653 additions and 474 deletions

View File

@ -3,9 +3,13 @@
![LOGO](https://d1z75bzl1vljy2.cloudfront.net/img/gp-logo.png)
#### Get the word out!
#### Get the word out
<br>
<span style="color:gray">Slideshow Presentations For Your GitHub Projects</span>
<span style="color:gray">Slideshow Presentations For Developers</span>
<br>
<span style="color:gray">on</span>
<br>
<span style="color:gray">GitHub - GitLab - Bitbucket</span>
#HSLIDE
@ -35,7 +39,7 @@ Create GitPitch slideshow content using GitHub flavored Markdown in your favorit
![TERMINAL](https://d1z75bzl1vljy2.cloudfront.net/hello-world/terminal.png)
Git-commit on any repo branch and push your PITCHME.md to GitHub.
Git-commit on any branch and push your PITCHME.md to GitHub, GitLab or Bitbucket.
#HSLIDE
@ -43,11 +47,11 @@ Git-commit on any repo branch and push your PITCHME.md to GitHub.
<br>
<span style="font-size: 1.5em;"><span style="color:white">htt</span><span style="color:white">ps://git</span><span style="color: #e49436">pitch</span><span style="color: white">.com/<span style="color: #e49436">user</span>/<span style="color: #e49436">repo</span></span>
<span style="font-size: 1.3em;"><span style="color:white">htt</span><span style="color:white">ps://git</span><span style="color: #e49436">pitch</span><span style="color: white">.com/<span style="color: #e49436">user</span>/<span style="color: #e49436">repo</span>/<span style="color: #e49436">branch</span></span>
<br>
Instantly use your GitPitch slideshow URL to promote, pitch or present your GitHub project.
Instantly use your GitPitch slideshow URL to promote, pitch or present absolutely anything.
#HSLIDE
<!-- .slide: data-autoslide="11000" -->
@ -75,7 +79,7 @@ Instantly use your GitPitch slideshow URL to promote, pitch or present your GitH
- Multiple Themes And More
- <span style="color: #e49436">Plus...</span>
- Your Slideshow Is Part Of Your Project
- Under Git Version Control Within Your GitHub Repo
- Under Git Version Control Within Your Git Repo
#HSLIDE

View File

@ -1,6 +1,6 @@
[![GitPitch](https://gitpitch.com/assets/badge.svg)](https://gitpitch.com/gitpitch/gitpitch/master) [![Build Status](https://semaphoreci.com/api/v1/gitpitch/gitpitch/branches/master/shields_badge.svg)](https://semaphoreci.com/gitpitch/gitpitch)
# Slideshow Presentations For Your GitHub Projects
# Slideshow Presentations For Developers
#### WEBSITE: [www.gitpitch.com](https://gitpitch.com) | HOW-TO : [GitPitch Wiki](https://github.com/gitpitch/gitpitch/wiki) | TWITTER: [@gitpitch](https://twitter.com/gitpitch)
@ -12,9 +12,9 @@
## What is GitPitch?
GitPitch is a service that turns **[PITCHME.md](https://gitpitch.com/#gitpitch-pitchme-markdown)** markdown into online, interactive slideshows. You can use it to promote, pitch or present anything, including your own GitHub projects.
GitPitch is a service that turns **[PITCHME.md](https://gitpitch.com/#gitpitch-pitchme-markdown)** markdown into online and offline, interactive slideshows. You can use it to promote, pitch or present absolutely anything, including your own Git projects.
Each slideshow presentation is made instantly available online just as soon as you git-commit and push **PITCHME.md** on any branch within a public GitHub repo.
Each slideshow presentation is made instantly available online just as soon as you git-commit and push **PITCHME.md** on any branch within a public **GitHub**, **GitLab** or **Bitbucket** repo.
![URL](images/gp-url.jpg)
@ -27,13 +27,13 @@ If you ever find yourself needing to present a concept, design, library, integra
- To colleagues, clients or customers
- Or at meetups or conferences
Then GitPitch is for you. Simply capture your ideas in Markdown and let GitPitch automatically turn those ideas into compelling, responsive, online slideshow presentations.
Then GitPitch is for you. Simply capture your ideas in Markdown and let GitPitch automatically turn those ideas into compelling, responsive, online and offline slideshow presentations.
## How does GitPitch work?
![TERMINAL](images/gp-terminal.png)
No more Keynote. No more PowerPoint. Just Markdown. Then git-commit on any branch within a public GitHub repo.
No more Keynote. No more PowerPoint. Just Markdown. Then git-commit on any branch within a public GitHub, GitLab or Bitbucket repo.
## GitPitch slideshow presentations are compelling

View File

@ -23,6 +23,8 @@
*/
import com.gitpitch.factory.MarkdownModelFactory;
import com.gitpitch.git.*;
import com.gitpitch.git.vendors.*;
import com.gitpitch.models.Markdown;
import com.gitpitch.models.MarkdownModel;
import com.gitpitch.services.*;
@ -49,6 +51,10 @@ public class Module extends AbstractModule {
bind(ImageService.class).asEagerSingleton();
bind(VideoService.class).asEagerSingleton();
bind(GISTService.class).asEagerSingleton();
bind(GRSManager.class).asEagerSingleton();
bind(GitHub.class).asEagerSingleton();
bind(GitLab.class).asEagerSingleton();
bind(BitBucket.class).asEagerSingleton();
bind(FrontEndThreads.class).asEagerSingleton();
bind(BackEndThreads.class).asEagerSingleton();
bind(Dependencies.class).asEagerSingleton();

View File

@ -23,6 +23,8 @@
*/
package com.gitpitch.controllers;
import com.gitpitch.git.GRS;
import com.gitpitch.git.GRSManager;
import com.gitpitch.models.GitRepoModel;
import com.gitpitch.models.MarkdownModel;
import com.gitpitch.executors.FrontEndThreads;
@ -56,6 +58,7 @@ public class PitchController extends Controller {
private final PitchService pitchService;
private final FrontEndThreads frontEndThreads;
private final Dependencies deps;
private final GRSManager grsManager;
private final Configuration cfg;
private final WSClient ws;
private final Environment env;
@ -65,6 +68,7 @@ public class PitchController extends Controller {
public PitchController(PitchService pitchService,
FrontEndThreads frontEndThreads,
Dependencies deps,
GRSManager grsManager,
Configuration cfg,
WSClient ws,
Environment env) {
@ -72,6 +76,7 @@ public class PitchController extends Controller {
this.pitchService = pitchService;
this.frontEndThreads = frontEndThreads;
this.deps = deps;
this.grsManager = grsManager;
this.cfg = cfg;
this.ws = ws;
this.env = env;
@ -117,11 +122,13 @@ public class PitchController extends Controller {
public CompletionStage<Result> landing(String user,
String repo,
String branch,
String grs,
String theme,
String notes,
String offline) {
PitchParams pp = PitchParams.build(user, repo, branch, theme, notes);
PitchParams pp =
PitchParams.build(grsOnCall(grs), user, repo, branch, theme, notes);
boolean isOffline =
(offline == null) ? false : Boolean.parseBoolean(offline);
Optional<GitRepoModel> grmo = pitchService.cachedRepo(pp);
@ -134,7 +141,8 @@ public class PitchController extends Controller {
log.info("landing: [ cached, online ] {}", pp);
GitRepoModel grm = grmo.get();
GitRepoRenderer rndr = GitRepoRenderer.build(pp, grm, cfg);
GitRepoRenderer rndr =
GitRepoRenderer.build(pp, grm, cfg, grsManager.listGRS());
return CompletableFuture.completedFuture(
ok(com.gitpitch.views.html.Landing.render(rndr,
@ -149,7 +157,9 @@ public class PitchController extends Controller {
}, frontEndThreads.POOL)
.thenApply(fetched -> {
GitRepoRenderer rndr = GitRepoRenderer.build(pp, fetched, cfg);
GitRepoRenderer rndr =
GitRepoRenderer.build(pp, fetched, cfg,
grsManager.listGRS());
if (rndr.isValid()) {
if (isOffline)
@ -173,7 +183,8 @@ public class PitchController extends Controller {
/*
* Slideshow builds and renders a GitPitch slideshow page.
*/
public CompletionStage<Result> slideshow(String user,
public CompletionStage<Result> slideshow(String grs,
String user,
String repo,
String branch,
String theme,
@ -181,7 +192,8 @@ public class PitchController extends Controller {
String fragments,
String offline) {
PitchParams pp = PitchParams.build(user, repo, branch, theme, notes);
PitchParams pp =
PitchParams.build(grsOnCall(grs), user, repo, branch, theme, notes);
boolean printing =
(fragments == null) ? false : !Boolean.parseBoolean(fragments);
boolean isOffline =
@ -234,11 +246,13 @@ public class PitchController extends Controller {
/*
* Markdown processes and renders PITCHME.md markdown.
*/
public CompletionStage<Result> markdown(String user,
public CompletionStage<Result> markdown(String grs,
String user,
String repo,
String branch) {
PitchParams pp = PitchParams.build(user, repo, branch);
PitchParams pp =
PitchParams.build(grsOnCall(grs), user, repo, branch);
Optional<MarkdownModel> mdmo = pitchService.cachedMarkdown(pp);
if (mdmo.isPresent()) {
@ -263,10 +277,12 @@ public class PitchController extends Controller {
}
if (pp.isMaster()) {
log.info("markdown: [ notfnd, online ] {}", pp);
return ok(RFE.build(pp)).as("text/markdown");
return ok(RFE.master(pp, grsManager.get(pp)))
.as("text/markdown");
} else {
log.info("markdown: [ notfnd, online ] {}", pp);
return ok(RFE.PITCHME_NOT_FOUND_ON_BRANCH).as("text/markdown");
return ok(RFE.branch(pp, grsManager.get(pp)))
.as("text/markdown");
}
});
}
@ -276,13 +292,15 @@ public class PitchController extends Controller {
/*
* Print generates and renders PITCHME.pdf.
*/
public CompletionStage<Result> print(String user,
public CompletionStage<Result> print(String grs,
String user,
String repo,
String branch,
String theme,
String notes) {
PitchParams pp = PitchParams.build(user, repo, branch, theme, notes);
PitchParams pp =
PitchParams.build(grsOnCall(grs), user, repo, branch, theme, notes);
Optional<File> pdfo = pitchService.cachedPDF(pp);
if (pdfo.isPresent()) {
@ -316,14 +334,17 @@ public class PitchController extends Controller {
/*
* Offline generates and renders PITCHME.zip.
*/
public CompletionStage<Result> offline(String user,
public CompletionStage<Result> offline(String grs,
String user,
String repo,
String branch,
String theme,
String notes) {
PitchParams pp = PitchParams.build(user, repo, branch, theme, notes);
log.debug("print: pp={}", pp);
PitchParams pp =
PitchParams.build(grsOnCall(grs), user, repo, branch, theme, notes);
log.debug("offline: pp={}", pp);
Optional<File> zipo = pitchService.cachedZip(pp);
@ -353,7 +374,7 @@ public class PitchController extends Controller {
});
}
} // print action
} // offline action
/*
* Gist generates and renders GitHub-Gist HTML for
@ -363,6 +384,13 @@ public class PitchController extends Controller {
return ok(com.gitpitch.views.html.Gist.render(gid, deps));
} // gist action
/*
* Determine GRS on call, explicitly defined or default.
*/
private String grsOnCall(String grsParam) {
return grsManager.getType(grsParam);
}
private static final String PITCHME_PRINT_ERROR =
"GitPitch Slideshow print service temporarily unavailable.";
private static final String PITCHME_OFFLINE_ERROR =

View File

@ -0,0 +1,104 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.git;
import com.gitpitch.utils.PitchParams;
import java.util.Map;
import java.util.HashMap;
/*
* Git Respository Service model.
*/
public class GRS {
private final String name;
private final String type;
private final String site;
private final String apiBase;
private final String apiToken;
private final String apiTokenHeader;
private final String rawBase;
private final boolean isDefault;
private GRS(String name,
String type,
String site,
String apiBase,
String apiToken,
String apiTokenHeader,
String rawBase,
boolean isDefault) {
this.name = name;
this.type = type;
this.site = site;
this.apiBase = apiBase;
this.apiToken = apiToken;
this.apiTokenHeader = apiTokenHeader;
this.rawBase = rawBase;
this.isDefault = isDefault;
}
public static GRS build(Map<String,String> grsCfg) {
String name = grsCfg.get("name");
String type = grsCfg.get("type");
String site = grsCfg.get("site");
String apiBase = grsCfg.get("apibase");
String apiToken = grsCfg.get("apitoken");
String apiTokenHeader = grsCfg.get("apitokenheader");
String rawBase = grsCfg.get("rawbase");
boolean isDefault = Boolean.parseBoolean(grsCfg.get("default"));
if(name != null && type != null && site != null &&
apiBase != null && rawBase != null) {
return new GRS(name, type, site, apiBase, apiToken,
apiTokenHeader, rawBase, isDefault);
} else {
return null;
}
}
public String getName() { return name; }
public String getType() { return type; }
public String getSite() { return site; }
public String getApiBase() { return apiBase; }
public String getApiToken() { return apiToken; }
public String getApiTokenHeader() { return apiTokenHeader; }
public String getRawBase() { return rawBase; }
public boolean isDefault() { return isDefault; }
public Map<String,String> getHeaders() {
Map<String,String> hdrs = new HashMap<String,String>();
if(getApiToken() != null && getApiTokenHeader() != null) {
hdrs.put(getApiTokenHeader(), getApiToken());
}
return hdrs;
}
public String toString() {
return "GRS[ " + name + " ][ " + type + " ]";
}
}

View File

@ -0,0 +1,170 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.git;
import com.gitpitch.git.vendors.*;
import com.gitpitch.services.DiskService;
import com.gitpitch.utils.PitchParams;
import java.util.*;
import java.util.stream.Collectors;
import javax.inject.*;
import play.Configuration;
import play.Logger;
import play.Logger.ALogger;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/*
* Git Repository Service manager.
*/
@Singleton
public class GRSManager {
private final Logger.ALogger log = Logger.of(this.getClass());
private final DiskService diskService;
private final GitHub gitHubService;
private final GitLab gitLabService;
private final BitBucket bitBucketService;
private final Configuration cfg;
private final Map<String,GRS> grsStore = new HashMap<String,GRS>();
private GRS grsDefault;
@Inject
public GRSManager(DiskService diskService,
GitHub gitHubService,
GitLab gitLabService,
BitBucket bitBucketService,
Configuration cfg) {
this.diskService = diskService;
this.gitHubService = gitHubService;
this.gitHubService.init(this, diskService);
this.gitLabService = gitLabService;
this.gitLabService.init(this, diskService);
this.bitBucketService = bitBucketService;
this.bitBucketService.init(this, diskService);
this.cfg = cfg;
List grsCfg = cfg.getList("gitpitch.git.repo.services");
List<HashMap<String,String>> grsCfgList = (List<HashMap<String,String>>) grsCfg;
GRS fallback = GRS.build(GRS_FALLBACK);
for(HashMap<String,String> grsMap : grsCfgList) {
GRS grs = GRS.build(grsMap);
if(grs != null) {
grsStore.put(grs.getType(), grs);
if(grs.isDefault())
grsDefault = grs;
} else {
log.warn("rejecting: {}", grsMap);
}
}
if(grsStore.isEmpty()) {
grsStore.put(fallback.getType(), fallback);
grsDefault = fallback;
log.info("fallback: {}, type={}, true",
grsDefault.getName(), grsDefault.getType());
}
if(grsDefault == null) {
grsDefault = fallback;
}
grsStore.forEach((k,v) -> {
log.info("activating: {}, type={}, default={}",
v.getName(), k, v.isDefault());
});
}
public GRS get(PitchParams pp) {
return get(pp.grs);
}
public GRS get(String grsType) {
GRS grs = grsStore.get(grsType);
return (grs != null) ? grs : grsDefault;
}
public String getType(String grsType) {
GRS grs = grsStore.get(grsType);
return (grs != null) ? grs.getType() : grsDefault.getType();
}
public GRSService getService(GRS grs) {
GRSService service;
switch(grs.getType()) {
case GitHub.TYPE:
log.debug("getService: matching GitHub");
service = gitHubService;
break;
case GitLab.TYPE:
log.debug("getService: matching GitLab");
service = gitLabService;
break;
case BitBucket.TYPE:
log.debug("getService: matching BitBucket");
service = bitBucketService;
break;
default:
log.debug("getService: defaulting GitHub");
service = gitHubService;
}
log.debug("getService: returning={}", service);
return service;
}
public List<GRS> listGRS() {
List<GRS> services = grsStore.entrySet()
.stream()
.map(Map.Entry::getValue)
.collect(Collectors.toList());
log.debug("listGRS: {}", services);
return services;
}
static Map<String,String> GRS_FALLBACK = new HashMap<String, String>();
static {
GRS_FALLBACK.put("name", "GitHub");
GRS_FALLBACK.put("type", "github");
GRS_FALLBACK.put("apibase", "https://api.github.com/");
GRS_FALLBACK.put("apitoken", null);
GRS_FALLBACK.put("rawbase", "https://raw.githubusercontent.com/");
GRS_FALLBACK.put("default", "true");
}
}

View File

@ -0,0 +1,132 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.git;
import com.gitpitch.git.*;
import com.gitpitch.models.GitRepoModel;
import com.gitpitch.utils.PitchParams;
import com.gitpitch.services.DiskService;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicInteger;
import com.fasterxml.jackson.databind.JsonNode;
import play.Logger;
import play.Logger.ALogger;
/*
* Git Respository Service common interface.
*/
public abstract class GRSService {
private final Logger.ALogger log = Logger.of(this.getClass());
protected final AtomicInteger cacheBypass = new AtomicInteger();
protected GRSManager grsManager;
protected DiskService diskService;
public void init(GRSManager grsManager,
DiskService diskService) {
this.grsManager = grsManager;
this.diskService = diskService;
}
/*
* Return true if apiPath is a call on this GRSService instance.
*/
public boolean call(PitchParams pp, String apiPath) {
if(apiPath != null) {
GRS grs = grsManager.get(pp);
return apiPath.startsWith(grs.getApiBase()) ||
apiPath.startsWith(grs.getRawBase());
} else {
return false;
}
}
/*
* Return zero if file download completes successfully.
*/
public int download(PitchParams pp, String filename) {
int status = 999;
GRS grs = grsManager.get(pp);
GRSService grsService = grsManager.getService(grs);
Path branchPath = diskService.ensure(pp);
String grsLink = raw(pp, filename, true);
log.debug("download: grsLink={}", grsLink);
if (grsService.call(pp, grsLink)) {
status = diskService.download(pp,
branchPath,
grsLink,
filename,
grs.getHeaders());
}
log.debug("download: returning status={}", status);
return status;
}
/*
* Return model representing Git repository meta-data.
*/
public abstract GitRepoModel model(PitchParams pp, JsonNode json);
/*
* Return Raw API path for /user/repo/branch.
*/
public abstract String raw(PitchParams pp);
/*
* Return Raw API path for /user/repo/branch/filename.
*/
public String raw(PitchParams pp, String filename) {
return raw(pp, filename, false);
}
/*
* Return Raw API path for /user/repo/branch/filename with
* optional query param used to bypass GRS API caching.
*/
public String raw(PitchParams pp,
String filename,
boolean bypassCache) {
if (bypassCache) {
return raw(pp) + filename +
"?gp=" + cacheBypass.getAndIncrement();
} else {
return raw(pp) + filename;
}
}
/*
* Return API path for repository meta call for /user/repo.
*/
public abstract String repo(PitchParams pp);
protected static final String SLASH = "/";
}

View File

@ -0,0 +1,78 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.git.vendors;
import com.gitpitch.git.*;
import com.gitpitch.models.*;
import com.gitpitch.utils.PitchParams;
import com.gitpitch.services.DiskService;
import com.fasterxml.jackson.databind.JsonNode;
import java.nio.file.Path;
import java.util.*;
import javax.inject.*;
import play.Logger;
import play.Logger.ALogger;
/*
* BitBucket API Service.
*/
@Singleton
public class BitBucket extends GRSService {
private final Logger.ALogger log = Logger.of(this.getClass());
public GitRepoModel model(PitchParams pp, JsonNode json) {
return BitBucketRepoModel.build(pp, json);
}
public String raw(PitchParams pp) {
GRS grs = grsManager.get(pp);
return new StringBuffer(grs.getRawBase())
.append(pp.user)
.append(SLASH)
.append(pp.repo)
.append(BITBUCKET_RAW)
.append(pp.branch)
.append(SLASH)
.toString();
}
public String repo(PitchParams pp) {
GRS grs = grsManager.get(pp);
return new StringBuffer(grs.getApiBase())
.append(BITBUCKET_REPO_API)
.append(pp.user)
.append(SLASH)
.append(pp.repo)
.toString();
}
public static final String TYPE = "bitbucket";
private static final String BITBUCKET_REPO_API = "repositories/";
private static final String BITBUCKET_RAW = "/raw/";
}

View File

@ -0,0 +1,77 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.git.vendors;
import com.gitpitch.git.*;
import com.gitpitch.models.*;
import com.gitpitch.services.DiskService;
import com.gitpitch.utils.PitchParams;
import com.fasterxml.jackson.databind.JsonNode;
import java.nio.file.Path;
import java.util.*;
import javax.inject.*;
import play.Logger;
import play.Logger.ALogger;
/*
* GitHub API Service.
*/
@Singleton
public class GitHub extends GRSService {
private final Logger.ALogger log = Logger.of(this.getClass());
public GitRepoModel model(PitchParams pp, JsonNode json) {
return GitHubRepoModel.build(pp, json);
}
public String raw(PitchParams pp) {
GRS grs = grsManager.get(pp);
return new StringBuffer(grs.getRawBase())
.append(pp.user)
.append(SLASH)
.append(pp.repo)
.append(SLASH)
.append(pp.branch)
.append(SLASH)
.toString();
}
public String repo(PitchParams pp) {
GRS grs = grsManager.get(pp);
return new StringBuffer(grs.getApiBase())
.append(GITHUB_REPO_API)
.append(pp.user)
.append(SLASH)
.append(pp.repo)
.toString();
}
public static final String TYPE = "github";
private static final String GITHUB_REPO_API = "repos/";
}

View File

@ -0,0 +1,88 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.git.vendors;
import com.gitpitch.git.*;
import com.gitpitch.models.*;
import com.gitpitch.services.DiskService;
import com.gitpitch.utils.PitchParams;
import com.fasterxml.jackson.databind.JsonNode;
import java.nio.file.Path;
import java.util.*;
import javax.inject.*;
import play.Logger;
import play.Logger.ALogger;
/*
* GitLab API Service.
*/
@Singleton
public class GitLab extends GRSService {
private final Logger.ALogger log = Logger.of(this.getClass());
public GitRepoModel model(PitchParams pp, JsonNode json) {
return GitLabRepoModel.build(pp, json);
}
public String raw(PitchParams pp) {
GRS grs = grsManager.get(pp);
return new StringBuffer(grs.getRawBase())
.append(pp.user)
.append(SLASH)
.append(pp.repo)
.append(GITLAB_RAW)
.append(pp.branch)
.append(SLASH)
.toString();
}
public String repo(PitchParams pp) {
GRS grs = grsManager.get(pp);
return new StringBuffer(grs.getApiBase())
.append(GITLAB_PROJECTS_API)
.append(genProjectId(pp))
.toString();
}
private String genProjectId(PitchParams pp) {
String userRepo =
new StringBuffer(pp.user).append(SLASH)
.append(pp.repo)
.toString();
String pid = java.net.URLEncoder.encode(userRepo);
log.debug("genProjectId: pid={}", pid);
return pid;
}
public static final String TYPE = "gitlab";
private static final String GITLAB_PROJECTS_API = "projects/";
private static final String GITLAB_RAW = "/raw/";
}

View File

@ -0,0 +1,146 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.models;
import com.fasterxml.jackson.databind.JsonNode;
import com.gitpitch.utils.PitchParams;
import play.Logger;
import play.Logger.ALogger;
import java.util.*;
/*
* Rendering model for views.Landing.scala.html.
*/
public class BitBucketRepoModel extends GitRepoModel {
private final Logger.ALogger log = Logger.of(this.getClass());
/*
* Initialize instance of BitBucketRepoModel.
*/
private BitBucketRepoModel(PitchParams pp) {
this(pp, null);
}
/*
* Initialize instance of BitBucketRepoModel.
*/
private BitBucketRepoModel(PitchParams pp,
JsonNode json) {
this._pp = pp;
this._pretty = new StringBuffer(SLASH)
.append(this._pp.user)
.append(SLASH)
.append(this._pp.repo)
.toString();
this._cacheKey = genKey(pp);
/*
* Generate derived data on instance only if the BitBucket
* API JSON is available for processing.
*/
if (json != null) {
JsonNode ownerNode = json.findPath("owner");
this._type = ownerNode.findPath("type").textValue();
this._desc = json.findPath("description").textValue();
this._created = json.findPath("created_on").textValue();
this._updated = json.findPath("updated_on").textValue();
this._lang = json.findPath("language").textValue();
this._stars = 0;
this._forks = 0;
this._issues = 0;
this._hasWiki = json.findPath("has_wiki").asBoolean();
this._hasPages = false;
} else {
this._type = null;
this._desc = null;
this._created = null;
this._updated = null;
this._lang = null;
this._stars = 0;
this._forks = 0;
this._issues = 0;
this._hasWiki = false;
this._hasPages = false;
}
}
public static GitRepoModel build(PitchParams pp) {
return build(pp, null);
}
public static GitRepoModel build(PitchParams pp, JsonNode json) {
return new BitBucketRepoModel(pp, json);
}
public String owner() {
return _pp.user;
}
public String name() {
return _pp.repo;
}
public String description() {
return _desc;
}
public String lang() {
return _lang;
}
public boolean byOrg() {
return GIT_TYPE_ORG.equals(_type);
}
public int stargazers() {
return _stars;
}
public int forks() {
return _forks;
}
public String toString() {
return _pretty;
}
public String key() {
return _cacheKey;
}
}

View File

@ -0,0 +1,146 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.models;
import com.fasterxml.jackson.databind.JsonNode;
import com.gitpitch.utils.PitchParams;
import play.Logger;
import play.Logger.ALogger;
import java.util.*;
/*
* Rendering model for views.Landing.scala.html.
*/
public class GitHubRepoModel extends GitRepoModel {
private final Logger.ALogger log = Logger.of(this.getClass());
/*
* Initialize instance of GitHubRepoModel.
*/
private GitHubRepoModel(PitchParams pp) {
this(pp, null);
}
/*
* Initialize instance of GitHubRepoModel.
*/
private GitHubRepoModel(PitchParams pp,
JsonNode json) {
this._pp = pp;
this._pretty = new StringBuffer(SLASH)
.append(this._pp.user)
.append(SLASH)
.append(this._pp.repo)
.toString();
this._cacheKey = genKey(pp);
/*
* Generate derived data on instance only if the GitHub
* API JSON is available for processing.
*/
if (json != null) {
JsonNode ownerNode = json.findPath("owner");
this._type = ownerNode.findPath("type").textValue();
this._desc = json.findPath("description").textValue();
this._created = json.findPath("created_at").textValue();
this._updated = json.findPath("updated_at").textValue();
this._lang = json.findPath("language").textValue();
this._stars = json.findPath("stargazers_count").asInt();
this._forks = json.findPath("forks_count").asInt();
this._issues = json.findPath("open_issues").asInt();
this._hasWiki = json.findPath("has_wiki").asBoolean();
this._hasPages = json.findPath("has_pages").asBoolean();
} else {
this._type = null;
this._desc = null;
this._created = null;
this._updated = null;
this._lang = null;
this._stars = 0;
this._forks = 0;
this._issues = 0;
this._hasWiki = false;
this._hasPages = false;
}
}
public static GitRepoModel build(PitchParams pp) {
return build(pp, null);
}
public static GitRepoModel build(PitchParams pp, JsonNode json) {
return new GitHubRepoModel(pp, json);
}
public String owner() {
return _pp.user;
}
public String name() {
return _pp.repo;
}
public String description() {
return _desc;
}
public String lang() {
return _lang;
}
public boolean byOrg() {
return GIT_TYPE_ORG.equals(_type);
}
public int stargazers() {
return _stars;
}
public int forks() {
return _forks;
}
public String toString() {
return _pretty;
}
public String key() {
return _cacheKey;
}
}

View File

@ -0,0 +1,150 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.models;
import com.fasterxml.jackson.databind.JsonNode;
import com.gitpitch.utils.PitchParams;
import play.Logger;
import play.Logger.ALogger;
import java.util.*;
/*
* Rendering model for views.Landing.scala.html.
*/
public class GitLabRepoModel extends GitRepoModel {
private final Logger.ALogger log = Logger.of(this.getClass());
/*
* Initialize instance of GitLabRepoModel.
*/
private GitLabRepoModel(PitchParams pp) {
this(pp, null);
}
/*
* Initialize instance of GitLabRepoModel.
*/
private GitLabRepoModel(PitchParams pp,
JsonNode json) {
this._pp = pp;
this._pretty = new StringBuffer(SLASH)
.append(this._pp.user)
.append(SLASH)
.append(this._pp.repo)
.toString();
this._cacheKey = genKey(pp);
/*
* Generate derived data on instance only if the GitLab
* API JSON is available for processing.
*/
if (json != null) {
this._type = USER_TYPE;
this._desc = json.findPath("description").textValue();
this._lang = null;
JsonNode namespaceNode = json.findPath("namespace");
if(namespaceNode != null) {
this._created = namespaceNode.findPath("created_at").textValue();
this._updated = namespaceNode.findPath("updated_at").textValue();
}
this._stars = json.findPath("star_count").asInt();
this._forks = json.findPath("forks_count").asInt();
this._issues = json.findPath("open_issues_count").asInt();
this._hasWiki = json.findPath("wiki_enabled").asBoolean();
this._hasPages = false;
} else {
this._type = null;
this._desc = null;
this._created = null;
this._updated = null;
this._lang = null;
this._stars = 0;
this._forks = 0;
this._issues = 0;
this._hasWiki = false;
this._hasPages = false;
}
}
public static GitRepoModel build(PitchParams pp) {
return build(pp, null);
}
public static GitRepoModel build(PitchParams pp, JsonNode json) {
return new GitLabRepoModel(pp, json);
}
public String owner() {
return _pp.user;
}
public String name() {
return _pp.repo;
}
public String description() {
return _desc;
}
public String lang() {
return _lang;
}
public boolean byOrg() {
return GIT_TYPE_ORG.equals(_type);
}
public int stargazers() {
return _stars;
}
public int forks() {
return _forks;
}
public String toString() {
return _pretty;
}
public String key() {
return _cacheKey;
}
private static final String USER_TYPE = "User";
}

View File

@ -23,7 +23,6 @@
*/
package com.gitpitch.models;
import com.fasterxml.jackson.databind.JsonNode;
import com.gitpitch.utils.PitchParams;
import play.Logger;
import play.Logger.ALogger;
@ -33,124 +32,59 @@ import java.util.*;
/*
* Rendering model for views.Landing.scala.html.
*/
public class GitRepoModel {
public abstract class GitRepoModel {
private final Logger.ALogger log = Logger.of(this.getClass());
/*
* PitchParams.
*/
private final PitchParams _pp;
protected PitchParams _pp;
/*
* GitHub repository owner type: User or Organization.
* Git repository owner type: User or Organization.
*/
private final String _type;
protected String _type;
/*
* GitHub repository description.
* Git repository description.
*/
private final String _desc;
protected String _desc;
/*
* GitHub repository creation date.
* Git repository creation date.
*/
private final String _created;
protected String _created;
/*
* GitHub repository last updated date.
* Git repository last updated date.
*/
private final String _updated;
protected String _updated;
/*
* GitHub repository language.
* Git repository language.
*/
private final String _lang;
protected String _lang;
/*
* GitHub repository stargazers_count.
* Git repository stargazers_count.
*/
private final int _stars;
protected int _stars;
/*
* GitHub repository forks_count.
* Git repository forks_count.
*/
private final int _forks;
protected int _forks;
/*
* GitHub repository open issues count.
* Git repository open issues count.
*/
private final int _issues;
protected int _issues;
/*
* GitHub repository has Wiki flag.
* Git repository has Wiki flag.
*/
private final boolean _hasWiki;
protected boolean _hasWiki;
/*
* GitHub repository has Pages (website) flag.
* Git repository has Pages (website) flag.
*/
private final boolean _hasPages;
protected boolean _hasPages;
/*
* Derived immutable state.
*/
private final String _pretty;
private final String _cacheKey;
/*
* Initialize instance of GitRepoModel.
*/
public GitRepoModel(PitchParams pp) {
this(pp, null);
}
/*
* Initialize instance of GitRepoModel.
*/
public GitRepoModel(PitchParams pp,
JsonNode json) {
this._pp = pp;
this._pretty = new StringBuffer(SLASH)
.append(this._pp.user)
.append(SLASH)
.append(this._pp.repo)
.toString();
this._cacheKey = new StringBuffer(MODEL_ID)
.append(this._pretty)
.toString();
/*
* Generate derived data on instance only if the GitHub
* API JSON is available for processing.
*/
if (json != null) {
JsonNode ownerNode = json.findPath("owner");
this._type = ownerNode.findPath("type").textValue();
this._desc = json.findPath("description").textValue();
this._created = json.findPath("created_at").textValue();
this._updated = json.findPath("updated_at").textValue();
this._lang = json.findPath("language").textValue();
this._stars = json.findPath("stargazers_count").asInt();
this._forks = json.findPath("forks_count").asInt();
this._issues = json.findPath("open_issues").asInt();
this._hasWiki = json.findPath("has_wiki").asBoolean();
this._hasPages = json.findPath("has_pages").asBoolean();
} else {
this._type = null;
this._desc = null;
this._created = null;
this._updated = null;
this._lang = null;
this._stars = 0;
this._forks = 0;
this._issues = 0;
this._hasWiki = false;
this._hasPages = false;
}
}
protected String _pretty;
protected String _cacheKey;
/*
* Generate a key for querying the cache for matching GitRepoModel.
@ -158,6 +92,8 @@ public class GitRepoModel {
public static String genKey(PitchParams pp) {
return new StringBuffer(MODEL_ID).append(SLASH)
.append(pp.grs)
.append(SLASH)
.append(pp.user)
.append(SLASH)
.append(pp.repo)
@ -165,53 +101,39 @@ public class GitRepoModel {
}
/*
* Return GitHub repository owner.
* Return Git repository owner.
*/
public String owner() {
return _pp.user;
}
public abstract String owner();
/*
* Return GitHub repository name.
* Return Git repository name.
*/
public String name() {
return _pp.repo;
}
public abstract String name();
/*
* Return GitHub repository description.
* Return Git repository description.
*/
public String description() {
return _desc;
}
public abstract String description();
/*
* Return GitHub repository language.
* Return Git repository language.
*/
public String lang() {
return _lang;
}
public abstract String lang();
/*
* Return true if GitHub repository owner is an organization.
* Return true if Git repository owner is an organization.
*/
public boolean byOrg() {
return GIT_TYPE_ORG.equals(_type);
}
public abstract boolean byOrg();
/*
* Return number of GitHub repository stargazers.
* Return number of Git repository stargazers.
*/
public int stargazers() {
return _stars;
}
public abstract int stargazers();
/*
* Return number of GitHub repository forks.
* Return number of Git repository forks.
*/
public int forks() {
return _forks;
}
public abstract int forks();
public String toString() {
return _pretty;
@ -221,8 +143,8 @@ public class GitRepoModel {
return _cacheKey;
}
private static final String GIT_TYPE_ORG = "Organization";
private static final String SLASH = "/";
protected static final String GIT_TYPE_ORG = "Organization";
protected static final String SLASH = "/";
/*
* Model prefix identifier for cache key generator.
*/

View File

@ -486,6 +486,8 @@ public class MarkdownModel implements Markdown {
public static String genKey(PitchParams pp) {
return new StringBuffer(MODEL_ID).append(SLASH)
.append(pp.grs)
.append(SLASH)
.append(pp.user)
.append(SLASH)
.append(pp.repo)

View File

@ -24,6 +24,7 @@
package com.gitpitch.models;
import com.gitpitch.models.MarkdownModel;
import com.gitpitch.git.GRSService;
import com.gitpitch.services.DiskService;
import com.gitpitch.utils.PitchParams;
import com.gitpitch.utils.YAMLOptions;
@ -71,7 +72,8 @@ public class SlideshowModel {
this._yOpts = yOpts;
this._fetchMarkdown =
com.gitpitch.controllers.routes.PitchController.markdown(pp.user,
com.gitpitch.controllers.routes.PitchController.markdown(pp.grs,
pp.user,
pp.repo,
pp.branch).url();
@ -83,17 +85,16 @@ public class SlideshowModel {
.append(this._pp.branch)
.toString();
this._cacheKey = new StringBuffer(MODEL_ID)
.append(this._pretty)
.toString();
this._cacheKey = genKey(pp);
}
public static SlideshowModel build(PitchParams pp,
boolean yamlFound,
GRSService grsService,
DiskService diskService) {
YAMLOptions yOpts =
yamlFound ? YAMLOptions.build(pp, diskService) : null;
yamlFound ? YAMLOptions.build(pp, grsService, diskService) : null;
return new SlideshowModel(pp, yOpts);
}
@ -103,6 +104,8 @@ public class SlideshowModel {
public static String genKey(PitchParams pp) {
return new StringBuffer(MODEL_ID).append(SLASH)
.append(pp.grs)
.append(SLASH)
.append(pp.user)
.append(SLASH)
.append(pp.repo)

View File

@ -23,7 +23,9 @@
*/
package com.gitpitch.services;
import com.gitpitch.utils.GitHub;
import com.gitpitch.git.GRS;
import com.gitpitch.git.GRSService;
import com.gitpitch.git.GRSManager;
import com.gitpitch.utils.PitchParams;
import org.apache.commons.io.FileUtils;
import play.Configuration;
@ -36,6 +38,7 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Map;
/*
* File system storage service.
@ -45,30 +48,31 @@ public class DiskService {
private final Logger.ALogger log = Logger.of(this.getClass());
private final String _storage;
private final String _decktape;
private final String _rawAuthToken;
private Configuration configuration;
private ShellService shellService;
private WSClient ws;
private final String storage;
private final String decktape;
private final String rawAuthToken;
private final ShellService shellService;
private final Configuration configuration;
private final WSClient ws;
@Inject
public DiskService(Configuration configuration,
ShellService shellService,
public DiskService(ShellService shellService,
Configuration configuration,
WSClient ws) {
this.configuration = configuration;
this.shellService = shellService;
this.configuration = configuration;
this.ws = ws;
this._storage = configuration.getString("gitpitch.storage.home");
this._decktape = configuration.getString("gitpitch.decktape.home");
this._rawAuthToken = configuration.getString("gitpitch.raw.auth.token");
this.storage = configuration.getString("gitpitch.storage.home");
this.decktape = configuration.getString("gitpitch.decktape.home");
this.rawAuthToken = configuration.getString("gitpitch.raw.auth.token");
}
/*
* Return PitchParams branch working directory.
*/
public Path bwd(PitchParams pp) {
return Paths.get(storage(), pp.user, pp.repo, pp.branch);
return Paths.get(storage(), pp.grs, pp.user, pp.repo, pp.branch);
}
/*
@ -76,7 +80,7 @@ public class DiskService {
*/
public Path asPath(PitchParams pp,
String filename) {
return Paths.get(storage(), pp.user, pp.repo, pp.branch, filename);
return Paths.get(storage(), pp.grs, pp.user, pp.repo, pp.branch, filename);
}
/*
@ -112,7 +116,8 @@ public class DiskService {
public int download(PitchParams pp,
Path wd,
String source,
String dest) {
String dest,
Map<String,String> headers) {
int downloaded = 999;
@ -126,20 +131,13 @@ public class DiskService {
final long start = System.currentTimeMillis();
WSRequest downloadReq = ws.url(source);
final WSRequest downloadReq = ws.url(source);
if (GitHub.call(source)) {
downloadReq =
downloadReq.setHeader(API_CACHE_CONTROL, API_NO_CACHE);
if (rawAuthToken() != null) {
String tokenValue = API_HEADER_TOKEN + rawAuthToken();
downloadReq =
downloadReq.setHeader(API_HEADER_AUTH, tokenValue);
}
}
headers.forEach((k,v) -> {
downloadReq.setHeader(k, v);
});
WSResponse downloadResp =
downloadReq.get().toCompletableFuture().get();
@ -273,18 +271,18 @@ public class DiskService {
* Return disk storage home directory.
*/
public String storage() {
return _storage;
return storage;
}
/*
* Return DeckTape PDF Exporter home directory.
*/
public String decktape() {
return _decktape;
return decktape;
}
public String rawAuthToken() {
return _rawAuthToken;
return rawAuthToken;
}
private static final Integer STATUS_OK = 0;

View File

@ -25,6 +25,7 @@ package com.gitpitch.services;
import com.fasterxml.jackson.databind.JsonNode;
import com.gitpitch.factory.MarkdownModelFactory;
import com.gitpitch.git.*;
import com.gitpitch.models.GitRepoModel;
import com.gitpitch.models.MarkdownModel;
import com.gitpitch.models.SlideshowModel;
@ -58,6 +59,7 @@ public class GitService {
private final ConcurrentHashMap<String, CountDownLatch> markdownLatchMap =
new ConcurrentHashMap();
private final GRSManager grsManager;
private final DiskService diskService;
private final PrintService printService;
private final ShellService shellService;
@ -69,7 +71,8 @@ public class GitService {
private final Configuration configuration;
@Inject
public GitService(DiskService diskService,
public GitService(GRSManager grsManager,
DiskService diskService,
PrintService printService,
ShellService shellService,
CacheTimeout cacheTimeout,
@ -79,6 +82,7 @@ public class GitService {
CacheApi pitchCache,
Configuration configuration) {
this.grsManager = grsManager;
this.diskService = diskService;
this.printService = printService;
this.shellService = shellService;
@ -114,15 +118,18 @@ public class GitService {
} else {
String apiCall = GitHub.repoAPI(pp);
GRS grs = grsManager.get(pp);
final GRSService grsService = grsManager.getService(grs);
String apiCall = grsService.repo(pp);
log.debug("fetchRepo: apiCall={}", apiCall);
final long start = System.currentTimeMillis();
WSRequest apiRequest = wsClient.url(apiCall);
if (githubApiToken() != null) {
String tokenValue = API_HEADER_TOKEN + githubApiToken();
apiRequest = apiRequest.setHeader(API_HEADER_AUTH, tokenValue);
}
grs.getHeaders().forEach((k,v) -> {
apiRequest.setHeader(k, v);
});
CompletableFuture<WSResponse> apiFuture =
apiRequest.get().toCompletableFuture();
@ -133,7 +140,8 @@ public class GitService {
log.debug("fetchRepo: pp={}, fetch meta time-taken={}",
pp, (System.currentTimeMillis() - start));
log.info("GitHub: API Rate Limit Status [ {}, {} ]",
log.info("{}: API Rate Limit Status [ {}, {} ]",
grs.getName(),
apiResp.getHeader(API_RATE_LIMIT),
apiResp.getHeader(API_RATE_LIMIT_REMAINING));
@ -144,7 +152,7 @@ public class GitService {
try {
JsonNode json = apiResp.asJson();
GitRepoModel grm = new GitRepoModel(pp, json);
GitRepoModel grm = grsService.model(pp, json);
/*
* Update pitchCache with new GitRepoModel
@ -173,7 +181,7 @@ public class GitService {
Integer.parseInt(remainingHdr);
if (rateLimitRemaining <= 0) {
log.warn("WARNING! GitHub API rate limit exceeded.");
log.warn("WARNING! {} API rate limit exceeded.", grs.getName());
}
} catch (Exception rlex) {
@ -238,10 +246,9 @@ public class GitService {
CompletableFuture<Void> syncFuture =
CompletableFuture.supplyAsync(() -> {
Path branchPath = diskService.ensure(pp);
String yamlLink = GitHub.rawAPI(pp, PITCHME_YAML, true);
int downYAML =
diskService.download(pp, branchPath, yamlLink, PITCHME_YAML);
GRS grs = grsManager.get(pp);
GRSService grsService = grsManager.getService(grs);
int downYAML = grsService.download(pp, PITCHME_YAML);
boolean downOk = downYAML == STATUS_OK;
log.debug("fetchYAML: pp={}, downloaded YAML={}", pp, downYAML);
@ -249,7 +256,7 @@ public class GitService {
* Update pitchCache with new SlideshowModel.
*/
SlideshowModel ssm =
SlideshowModel.build(pp, downOk, diskService);
SlideshowModel.build(pp, downOk, grsService, diskService);
pitchCache.set(ssm.key(), ssm, cacheTimeout.ssm(pp));
/*
@ -307,18 +314,18 @@ public class GitService {
CompletableFuture<Void> syncFuture =
CompletableFuture.supplyAsync(() -> {
Path branchPath = diskService.ensure(pp);
String mdLink = GitHub.rawAPI(pp, PITCHME_MD, true);
int downStatus =
diskService.download(pp, branchPath, mdLink, PITCHME_MD);
GRS grs = grsManager.get(pp);
GRSService grsService = grsManager.getService(grs);
int downStatus = grsService.download(pp, PITCHME_MD);
if (downStatus == STATUS_OK) {
String ssmKey = SlideshowModel.genKey(pp);
Optional<SlideshowModel> ssm =
Optional.ofNullable(pitchCache.get(ssmKey));
MarkdownRenderer mrndr =
MarkdownRenderer.build(pp, ssm, diskService);
MarkdownRenderer mrndr = MarkdownRenderer.build(pp,
ssm, grsService, diskService);
// MarkdownModel mdm = MarkdownModel.consume(mrndr);
MarkdownModel mdm =
@ -378,10 +385,6 @@ public class GitService {
}
public String githubApiToken() {
return configuration.getString("gitpitch.github.api.token");
}
private static final String GHUB_REPO_META =
"https://api.github.com/repos/";
private static final String GIT_MASTER = "master";

View File

@ -24,6 +24,7 @@
package com.gitpitch.services;
import com.gitpitch.factory.MarkdownModelFactory;
import com.gitpitch.git.*;
import com.gitpitch.models.MarkdownModel;
import com.gitpitch.models.SlideshowModel;
import com.gitpitch.executors.BackEndThreads;
@ -60,21 +61,24 @@ public class OfflineService {
private final Logger.ALogger log = Logger.of(this.getClass());
private DiskService diskService;
private ShellService shellService;
private MarkdownModelFactory markdownModelFactory;
private BackEndThreads backEndThreads;
private Configuration configuration;
private Environment env;
private final GRSManager grsManager;
private final DiskService diskService;
private final ShellService shellService;
private final MarkdownModelFactory markdownModelFactory;
private final BackEndThreads backEndThreads;
private final Configuration configuration;
private final Environment env;
@Inject
public OfflineService(DiskService diskService,
public OfflineService(GRSManager grsManager,
DiskService diskService,
ShellService shellService,
MarkdownModelFactory markdownModelFactory,
BackEndThreads backEndThreads,
Configuration configuration,
Environment env) {
this.grsManager = grsManager;
this.diskService = diskService;
this.shellService = shellService;
this.markdownModelFactory = markdownModelFactory;
@ -230,14 +234,17 @@ public class OfflineService {
private int fetchOnlineMarkdown(PitchParams pp) {
String murl =
com.gitpitch.controllers.routes.PitchController.markdown(pp.user,
com.gitpitch.controllers.routes.PitchController.markdown(pp.grs,
pp.user,
pp.repo,
pp.branch)
.absoluteURL(isEncrypted(), hostname());
Path zipMdPath =
diskService.ensure(diskService.asPath(pp, ZIP_MD_DIR));
return diskService.download(pp, zipMdPath, murl, PITCHME_ONLINE_MD);
return diskService.download(pp,
zipMdPath, murl, PITCHME_ONLINE_MD,
grsManager.get(pp).getHeaders());
}
/*
@ -249,12 +256,14 @@ public class OfflineService {
com.gitpitch.controllers.routes.PitchController.landing(pp.user,
pp.repo,
pp.branch,
pp.grs,
pp.theme,
pp.notes,
ENABLED)
.absoluteURL(isEncrypted(), hostname());
return diskService.download(pp, zipRoot, lurl, INDEX_HTML);
return diskService.download(pp, zipRoot,
lurl, INDEX_HTML, grsManager.get(pp).getHeaders());
}
/*
@ -263,7 +272,8 @@ public class OfflineService {
private int fetchSlideshowHTML(PitchParams pp, Path zipRoot) {
String surl =
com.gitpitch.controllers.routes.PitchController.slideshow(pp.user,
com.gitpitch.controllers.routes.PitchController.slideshow(pp.grs,
pp.user,
pp.repo,
pp.branch,
pp.theme,
@ -272,7 +282,8 @@ public class OfflineService {
ENABLED)
.absoluteURL(isEncrypted(), hostname());
return diskService.download(pp, zipRoot, surl, SLIDESHOW_HTML);
return diskService.download(pp, zipRoot,
surl, SLIDESHOW_HTML, grsManager.get(pp).getHeaders());
}
/*
@ -322,8 +333,11 @@ public class OfflineService {
if (mdOnlineFile.exists()) {
GRSService grsService =
grsManager.getService(grsManager.get(pp));
MarkdownRenderer mrndr =
MarkdownRenderer.build(pp, ssmo, diskService);
MarkdownRenderer.build(pp, ssmo, grsService, diskService);
MarkdownModel markdownModel =
(MarkdownModel) markdownModelFactory.create(mrndr);
@ -384,9 +398,9 @@ public class OfflineService {
for (String assetUrl : assetUrls) {
if (assetUrl != null &&
!fetched.contains(assetUrl)) {
diskService.download(pp, zipMdAssetsPath,
assetUrl,
FilenameUtils.getName(assetUrl));
diskService.download(pp, zipMdAssetsPath, assetUrl,
FilenameUtils.getName(assetUrl),
grsManager.get(pp).getHeaders());
fetched.add(assetUrl);
}
}
@ -405,7 +419,9 @@ public class OfflineService {
*/
private void fetchYAMLDependencies(PitchParams pp) {
YAMLOptions yOpts = YAMLOptions.build(pp, diskService);
GRSService grsService =
grsManager.getService(grsManager.get(pp));
YAMLOptions yOpts = YAMLOptions.build(pp, grsService, diskService);
log.debug("fetchYAMLDependencies: yOpts={}", yOpts);
try {
@ -417,7 +433,8 @@ public class OfflineService {
Path zipAssetsPath =
diskService.ensure(diskService.asPath(pp,
ZIP_ASSETS_DIR));
diskService.download(pp, zipAssetsPath, logoUrl, logoName);
diskService.download(pp, zipAssetsPath,
logoUrl, logoName, grsManager.get(pp).getHeaders());
log.debug("fetchYAMLDependencies: downloaded logo={}", logoUrl);
}

View File

@ -77,6 +77,7 @@ public class PitchService {
public Optional<GitRepoModel> cachedRepo(PitchParams pp) {
String grmKey = GitRepoModel.genKey(pp);
log.debug("cachedRepo: grmKey={}", grmKey);
return Optional.ofNullable(pitchCache.get(grmKey));
}

View File

@ -153,7 +153,8 @@ public class PrintService {
String filePath = diskService.asFile(pp, PITCHME_PDF).toString();
String slideshowUrl =
com.gitpitch.controllers.routes.PitchController.slideshow(pp.user,
com.gitpitch.controllers.routes.PitchController.slideshow(pp.grs,
pp.user,
pp.repo,
pp.branch,
pp.theme,

View File

@ -1,99 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2016 David Russell
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.gitpitch.utils;
import com.gitpitch.utils.PitchParams;
import play.Logger;
import play.Logger.ALogger;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/*
* GitHub API endpoint utility.
*/
public final class GitHub {
private final static Logger.ALogger log =
Logger.of("com.gitpitch.utils.GitHub");
private static AtomicInteger atomicInt = new AtomicInteger();
public static String rawAPI(PitchParams pp) {
return new StringBuffer(GHUB_RAW_BASE)
.append(pp.user)
.append(SLASH)
.append(pp.repo)
.append(SLASH)
.append(pp.branch)
.append(SLASH)
.toString();
}
public static String rawAPI(PitchParams pp,
String filename) {
return rawAPI(pp, filename, false);
}
public static String rawAPI(PitchParams pp,
String filename,
boolean bypassCache) {
if (bypassCache) {
/*
* Adding ?gp={rand} to the URL ensures that the
* GitHub cache does not return cached data.
*/
return rawAPI(pp) + filename + "?gp=" + atomicInt.getAndIncrement();
} else {
return rawAPI(pp) + filename;
}
}
public static String repoAPI(PitchParams pp) {
return new StringBuffer(GHUB_REPO_META)
.append(pp.user)
.append(SLASH)
.append(pp.repo)
.toString();
}
public static boolean call(String url) {
if (url != null) {
return url.startsWith(GHUB_API_BASE) ||
url.startsWith(GHUB_RAW_BASE);
} else {
return false;
}
}
private static final String SLASH = "/";
private static final String GHUB_RAW_BASE = "https://raw.githubusercontent.com/";
private static final String GHUB_API_BASE = "https://api.github.com";
private static final String GHUB_REPO_META = GHUB_API_BASE + "/repos/";
}

View File

@ -23,14 +23,17 @@
*/
package com.gitpitch.utils;
import com.gitpitch.git.GRS;
import com.gitpitch.git.vendors.*;
import com.gitpitch.models.GitRepoModel;
import com.gitpitch.utils.PitchParams;
import play.Configuration;
import play.Logger;
import play.Logger.ALogger;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import play.Logger;
import play.Logger.ALogger;
/*
* Rendering model for views.Landing.scala.html.
@ -42,6 +45,7 @@ public class GitRepoRenderer {
private final PitchParams _pp;
private final GitRepoModel _grm;
private Configuration _cfg;
private List<GRS> _grsServices;
/*
* Relative URLs for view components.
*/
@ -57,17 +61,19 @@ public class GitRepoRenderer {
private String _starHub;
private String _forkHub;
private GitRepoRenderer(PitchParams pp) {
this(pp, null, null);
private GitRepoRenderer(PitchParams pp, List<GRS> grsServices) {
this(pp, null, null, grsServices);
}
private GitRepoRenderer(PitchParams pp,
GitRepoModel grm,
Configuration cfg) {
Configuration cfg,
List<GRS> grsServices) {
this._pp = pp;
this._grm = grm;
this._cfg = cfg;
this._grsServices = grsServices;
if (grm != null) {
@ -77,25 +83,49 @@ public class GitRepoRenderer {
*/
this._landingURL = com.gitpitch.controllers.routes.PitchController
.landing(_grm.owner(),
.landing(_pp.grs,
_grm.owner(),
_grm.name(),
_pp.branch,
_pp.theme,
_pp.notes, null).toString();
this._slideshowURL = com.gitpitch.controllers.routes.PitchController
.slideshow(_grm.owner(),
.slideshow(_pp.grs,
_grm.owner(),
_grm.name(),
_pp.branch,
_pp.theme,
_pp.notes, null, null).toString();
this._markdownURL = com.gitpitch.controllers.routes.PitchController
.markdown(_grm.owner(),
.markdown(_pp.grs,
_grm.owner(),
_grm.name(),
_pp.branch).toString();
this._orgHub = new StringBuffer(GIT_COM).append(_grm.owner())
Optional<GRS> grso =
this._grsServices.stream()
.filter(grs -> grs.getType().equals(_pp.grs))
.findFirst();
Optional<GRS> grsoDefault =
this._grsServices.stream()
.filter(grs -> grs.isDefault())
.findFirst();
String grsSite = null;
if(grso.isPresent()) {
grsSite = grso.get().getSite();
} else {
if(grsoDefault.isPresent())
grsSite = grsoDefault.get().getSite();
else
grsSite = GRS_GITHUB_COM;
}
this._orgHub = new StringBuffer(grsSite).append(_grm.owner())
.toString();
this._repoHub =
@ -103,14 +133,45 @@ public class GitRepoRenderer {
.append(this._grm.name())
.toString();
switch(_pp.grs) {
this._starHub = new StringBuffer(this._repoHub).append(SLASH)
.append(STARGAZERS)
case GitHub.TYPE:
this._starHub =
new StringBuffer(this._repoHub).append(SLASH)
.append(GRS_GITHUB_STARS)
.toString();
this._forkHub =
new StringBuffer(this._repoHub).append(SLASH)
.append(GRS_GITHUB_FORKS)
.toString();
break;
case GitLab.TYPE:
this._starHub =
new StringBuffer(this._repoHub).append(SLASH)
.append(GRS_GITLAB_STARS)
.toString();
this._forkHub =
new StringBuffer(this._repoHub).append(SLASH)
.append(GRS_GITLAB_FORKS)
.append(_pp.branch)
.toString();
break;
case BitBucket.TYPE:
this._starHub =
new StringBuffer(this._repoHub).append(SLASH)
.append(GRS_BITBUCKET_STARS)
.toString();
this._forkHub =
new StringBuffer(this._repoHub).append(SLASH)
.append(GRS_BITBUCKET_FORKS)
.toString();
break;
this._forkHub = new StringBuffer(this._repoHub).append(SLASH)
.append(FORKS)
.toString();
default:
this._starHub = "#";
this._forkHub = "#";
break;
}
} else {
/*
@ -130,9 +191,10 @@ public class GitRepoRenderer {
public static GitRepoRenderer build(PitchParams pp,
GitRepoModel grm,
Configuration cfg) {
Configuration cfg,
List<GRS> grsServices) {
return new GitRepoRenderer(pp, grm, cfg);
return new GitRepoRenderer(pp, grm, cfg, grsServices);
}
/*
@ -202,7 +264,8 @@ public class GitRepoRenderer {
* Return relative URL to landing view.
*/
public String landingURL(String theme) {
return com.gitpitch.controllers.routes.PitchController.landing(_grm.owner(),
return com.gitpitch.controllers.routes.PitchController.landing(_pp.grs,
_grm.owner(),
_grm.name(),
_pp.branch,
theme,
@ -269,7 +332,15 @@ public class GitRepoRenderer {
* Return GitHub repository language.
*/
public String repoLang() {
return (_grm != null) ? _grm.lang() : null;
String repoLang = null;
if(_grm != null) {
if(_grm.lang() != null && _grm.lang().length() > 0) {
repoLang = _grm.lang();
}
}
return repoLang;
}
/*
@ -300,19 +371,28 @@ public class GitRepoRenderer {
}
public String pageLink(boolean absolute) {
return pageLink(absolute, null);
}
public String pageLink(boolean absolute, String grs) {
grs = (grs != null) ? grs : _pp.grs;
if (absolute)
return com.gitpitch.controllers.routes.PitchController.landing(_pp.user,
_pp.repo,
_pp.branch,
grs,
_pp.theme,
_pp.notes, null)
_pp.notes,
null)
.absoluteURL(isEncrypted(),
hostname());
else
return com.gitpitch.controllers.routes.PitchController.landing(_pp.user,
_pp.repo,
_pp.branch,
grs,
_pp.theme,
_pp.notes, null).toString();
}
@ -322,13 +402,16 @@ public class GitRepoRenderer {
return com.gitpitch.controllers.routes.PitchController.landing(_pp.user,
_pp.repo,
_pp.branch,
_pp.grs,
theme,
_pp.notes, null).toString();
_pp.notes,
null).toString();
}
public String printLink() {
return com.gitpitch.controllers.routes.PitchController.print(_pp.user,
return com.gitpitch.controllers.routes.PitchController.print(_pp.grs,
_pp.user,
_pp.repo,
_pp.branch,
_pp.theme,
@ -337,7 +420,8 @@ public class GitRepoRenderer {
public String offlineLink() {
return com.gitpitch.controllers.routes.PitchController.offline(_pp.user,
return com.gitpitch.controllers.routes.PitchController.offline(_pp.grs,
_pp.user,
_pp.repo,
_pp.branch,
_pp.theme,
@ -360,6 +444,20 @@ public class GitRepoRenderer {
.toString();
}
public String getGRS(PitchParams pp) {
String grsName = null;
for(GRS grs : _grsServices) {
if(grs.getType().equals(pp.grs)) {
grsName = grs.getName();
}
}
return grsName;
}
public List<GRS> listGRS() {
return _grsServices;
}
/*
* Return string representation of ViewModel.
*/
@ -382,9 +480,6 @@ public class GitRepoRenderer {
private static final String SLASH = "/";
private static final String QMARK_BRANCH = "?b=";
private static final String QMARK_THEME = "&t=";
private static final String GIT_COM = "https://github.com/";
private static final String STARGAZERS = "stargazers";
private static final String FORKS = "network";
private static final String HTTP_HASH = "#";
private static final String EMBED_OPEN =
"<iframe width='770' height='515' src='";
@ -396,4 +491,12 @@ public class GitRepoRenderer {
private static final String DEFAULT_THEME = "white";
private static final List<String> THEMES = Arrays.asList(DEFAULT_THEME,
"beige", "black", "moon", "night", "sky", "white");
private static final String GRS_GITHUB_COM = "https://github.com/";
private static final String GRS_GITHUB_STARS = "stargazers";
private static final String GRS_GITHUB_FORKS = "network";
private static final String GRS_GITLAB_STARS = "activity";
private static final String GRS_GITLAB_FORKS = "graphs/";
private static final String GRS_BITBUCKET_STARS = "commits/all";
private static final String GRS_BITBUCKET_FORKS = "branches";
}

View File

@ -23,9 +23,9 @@
*/
package com.gitpitch.utils;
import com.gitpitch.git.GRSService;
import com.gitpitch.models.SlideshowModel;
import com.gitpitch.services.DiskService;
import com.gitpitch.utils.GitHub;
import play.Logger;
import java.nio.file.Path;
@ -40,22 +40,26 @@ public class MarkdownRenderer {
private final PitchParams _pp;
private final Optional<SlideshowModel> _ssm;
private GRSService grsService;
private DiskService diskService;
private MarkdownRenderer(PitchParams pp,
Optional<SlideshowModel> ssm,
GRSService grsService,
DiskService diskService) {
this._pp = pp;
this._ssm = ssm;
this.grsService = grsService;
this.diskService = diskService;
}
public static MarkdownRenderer build(PitchParams pp,
Optional<SlideshowModel> ssm,
GRSService grsService,
DiskService diskService) {
return new MarkdownRenderer(pp, ssm, diskService);
return new MarkdownRenderer(pp, ssm, grsService, diskService);
}
public PitchParams pp() {
@ -67,7 +71,7 @@ public class MarkdownRenderer {
}
public String gitRawBase() {
return GitHub.rawAPI(_pp);
return grsService.raw(_pp);
}
public Path filePath(String filename) {

View File

@ -36,30 +36,36 @@ public class PitchParams {
public String branch;
public String theme;
public String notes;
public String grs;
private PitchParams(String user,
private PitchParams(String grs,
String user,
String repo) {
this(user, repo, null, null);
this(grs, user, repo, null);
}
private PitchParams(String user,
private PitchParams(String grs,
String user,
String repo,
String branch) {
this(user, repo, branch, null);
this(grs, user, repo, branch, null);
}
private PitchParams(String user,
private PitchParams(String grs,
String user,
String repo,
String branch,
String theme) {
this(user, repo, branch, theme, null);
this(grs, user, repo, branch, theme, null);
}
private PitchParams(String user,
private PitchParams(String grs,
String user,
String repo,
String branch,
String theme,
String notes) {
this.grs = grs;
this.user = user;
this.repo = repo;
@ -73,34 +79,38 @@ public class PitchParams {
this.notes = notes;
}
public static PitchParams build(String user,
public static PitchParams build(String grs,
String user,
String repo) {
return new PitchParams(user, repo);
return new PitchParams(grs, user, repo);
}
public static PitchParams build(String user,
public static PitchParams build(String grs,
String user,
String repo,
String branch) {
return new PitchParams(user, repo, branch);
return new PitchParams(grs, user, repo, branch);
}
public static PitchParams build(String user,
public static PitchParams build(String grs,
String user,
String repo,
String branch,
String theme) {
return new PitchParams(user, repo, branch, theme);
return new PitchParams(grs, user, repo, branch, theme);
}
public static PitchParams build(String user,
public static PitchParams build(String grs,
String user,
String repo,
String branch,
String theme,
String notes) {
return new PitchParams(user, repo, branch, theme, notes);
return new PitchParams(grs, user, repo, branch, theme, notes);
}
public static boolean isDarkTheme(String theme) {
@ -133,7 +143,9 @@ public class PitchParams {
}
public String pretty() {
return new StringBuffer(SLASH).append(user)
return new StringBuffer(SLASH).append(grs)
.append(SLASH)
.append(user)
.append(SLASH)
.append(repo)
.append(SLASH)
@ -142,7 +154,9 @@ public class PitchParams {
}
public String toString() {
return new StringBuffer(SLASH).append(user)
return new StringBuffer(SLASH).append(grs)
.append(SLASH)
.append(user)
.append(SLASH)
.append(repo)
.append(SLASH)

View File

@ -23,6 +23,7 @@
*/
package com.gitpitch.utils;
import com.gitpitch.git.GRS;
import com.gitpitch.utils.PitchParams;
import java.util.StringJoiner;
@ -36,22 +37,19 @@ public final class RFE {
* chance to submit a Feature Request (Issue)
* against the repo identified by PitchParams.
*/
public static String build(PitchParams pp) {
public static String master(PitchParams pp, GRS grs) {
String newIssue = "https://github.com/" +
pp.user + "/" + pp.repo + "/issues/new?title=" +
"GitPitch - Let's get the word out!" +
"&body=I would really like to see a " +
"[GitPitch slideshow presentation](https://gitpitch.com) for this repo." +
" Help me help you get the word out, " +
"just add PITCHME.md. @gitpitch";
String newIssue = grs.getSite() +
pp.user + "/" + pp.repo + "/issues/new";
StringBuffer buf = new StringBuffer();
buf.append("<span style=\"font-size:1.1em\">PITCHME.md 404</span><br><br>")
.append("\n\n")
.append("<span style=\"font-size:0.9em\">")
.append("Would you like to submit a feature request to the ")
.append("repository owner asking them to add a GitPitch for this repo?")
.append("repository owner asking them to add a GitPitch for this repo on ")
.append(grs.getName())
.append("?")
.append(" If so, click <a target=\"_blank\" href=\"")
.append(newIssue)
.append("\">here.</a></span>");
@ -59,9 +57,15 @@ public final class RFE {
return buf.toString();
}
public static final String PITCHME_NOT_FOUND_ON_BRANCH =
new StringJoiner("\n\n").add("<span style=\"font-size:1.1em\">PITCHME.md 404</span><br><br>")
.add("<span style=\"font-size:0.9em\">No GitPitch found for this branch.</span>")
.toString();
public static String branch(PitchParams pp, GRS grs) {
return new StringBuffer("<span style=\"font-size:1.1em\">")
.append("PITCHME.md 404</span><br><br>")
.append("\n\n")
.append("<span style=\"font-size:0.9em\">")
.append("No GitPitch found for this branch on ")
.append(grs.getName())
.append(".</span>")
.toString();
}
}

View File

@ -23,6 +23,7 @@
*/
package com.gitpitch.utils;
import com.gitpitch.git.GRSService;
import com.gitpitch.services.DiskService;
import org.yaml.snakeyaml.Yaml;
import play.Logger;
@ -42,12 +43,16 @@ public final class YAMLOptions {
Logger.of("com.gitpitch.utils.YAMLOptions");
private final Map<String, String> _yProps;
private final GRSService grsService;
private YAMLOptions(Map<String, String> yProps) {
private YAMLOptions(Map<String, String> yProps,
GRSService grsService) {
this._yProps = yProps;
this.grsService = grsService;
}
public static YAMLOptions build(PitchParams pp,
GRSService grsService,
DiskService diskService) {
YAMLOptions yOpts = null;
@ -82,7 +87,7 @@ public final class YAMLOptions {
log.debug("build: pp={}, props={}", pp, yProps);
yOpts = new YAMLOptions(yProps);
yOpts = new YAMLOptions(yProps, grsService);
} else {
log.debug("build: pp={}, yaml not found={}", yFile);
}
@ -125,7 +130,7 @@ public final class YAMLOptions {
if (isAbsolute(overridePath)) {
return overridePath;
} else {
return GitHub.rawAPI(pp, overridePath);
return grsService.raw(pp, overridePath);
}
}
@ -140,7 +145,7 @@ public final class YAMLOptions {
if (isAbsolute(logoPath)) {
return logoPath;
} else {
return GitHub.rawAPI(pp, logoPath);
return grsService.raw(pp, logoPath);
}
}
@ -155,7 +160,7 @@ public final class YAMLOptions {
if (isAbsolute(imgBgPath)) {
return imgBgPath;
} else {
return GitHub.rawAPI(pp, imgBgPath);
return grsService.raw(pp, imgBgPath);
}
}

View File

@ -12,12 +12,10 @@
<html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="description" content="GitPitch - Slideshow Presentations For Your GitHub Projects">
<meta name="keywords"
content="GitPitch, GitHub, PITCHME, PITCHME.md, Slideshow, Presentation, Project">
<title>GitPitch - Slideshow Presentations For Your GitHub Projects</title>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<title>GitHub, GitLab, Bitbucket Slideshow Presentations For Developers - GitPitch</title>
<meta content="Got for it. Just add PITCHME.md ;)" name="description">
<meta content="GitHub, GitLab, Bitbucket, Markdown, Slideshow, Presentation, Developers, PITCHME" name="keywords">
<link rel="icon" href="@deps.gitpitchimg(offline)/favicon.ico"/>
<link href="@deps.bootstrap(offline)/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<link href="@deps.fontawesome(offline)/css/font-awesome.min.css" rel="stylesheet" type="text/css"/>
@ -55,9 +53,8 @@
</iframe>
} else {
<div id="messagebox" class="centered">
<span class="mega-octicon octicon-mark-github">
GitHub repository not found
<span class="mega-octicon octicon-stop"></span>
<span class="mega-octicon">Git repository not found on @rndr.getGRS(rndr.params())
<span class="octicon-stop"></span>
</span>
<div/>
}
@ -77,6 +74,18 @@
</div>
<script src="@deps.jquery(offline)/jquery.min.js"></script>
<script src="@deps.bootstrap(offline)/js/bootstrap.min.js"></script>
<script>
$(".dropdown-menu li a").click(function(){
// alert("DD: selected item");
// $(this).parents(".dropdown").find('.btn').html($(this).text() + ' <span class="caret"></span>');
// $(this).parents(".dropdown").find('.btn').val($(this).data('value'));
// alert("DD: selected item.text: " + $(this).text());
// alert("DD: selected item.data: " + $(this).data('value'));
$(".dropdown-toggle").html($(this).text() + ' <span class="caret">');
$(".dropdown-toggle").val($(this).data('value', $(this).data('value')));
});
</script>
@if(!offline) {
@LandingSocialDependencies(deps, offline)
}

View File

@ -6,11 +6,10 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="description" content="GitPitch - Slideshow Presentations For Your GitHub Projects">
<meta name="keywords"
content="GitPitch, GitHub, PITCHME, PITCHME.md, Slideshow, Presentation, Project">
<title>GitPitch - Slideshow Presentations For Your GitHub Projects</title>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<title>GitHub, GitLab, Bitbucket Slideshow Presentations For Developers - GitPitch</title>
<meta content="Got for it. Just add PITCHME.md ;)" name="description">
<meta content="GitHub, GitLab, Bitbucket, Markdown, Slideshow, Presentation, Developers, PITCHME" name="keywords">
<link rel="icon" href="@deps.gitpitchimg(offline)/favicon.ico"/>
<link href="@deps.revealjs(offline)/css/reveal.css" rel="stylesheet" type="text/css"/>
<link href="@deps.revealjs(offline)/css/theme/@ssm.fetchThemeCSS()" rel="stylesheet" type="text/css"/>
@ -19,6 +18,7 @@
}
<link href="@deps.highlightjs(offline)/@ssm.fetchHighlightCSS()" rel="stylesheet" type="text/css"/>
<link href="@deps.octicons(offline)/octicons.css" rel="stylesheet" type="text/css"/>
<link href="@deps.fontawesome(offline)/css/font-awesome.min.css" rel="stylesheet" type="text/css"/>
@SlideshowStyle()
@ -39,15 +39,14 @@
</div>
}
<div style="position: fixed; bottom: 10px; left: 20px; z-index: 999">
@if(ssm.params().darkTheme()) {
@if(ssm.params().grs.equals("github")) {
<span class="octicon octicon-mark-github"
style="font-size:0.9em; color: @ssm.fetchThemeFontColorInverse()"></span>
<span style="color:@ssm.fetchThemeFontColorInverse(); font-size:0.8em; font-family: @ssm.fetchThemeFont();">@ssm.params().asLogo()</span>
} else {
<span class="octicon octicon-mark-github"
style="font-size:0.9em; color: @ssm.fetchThemeFontColorInverse()"></span>
<span style="color:@ssm.fetchThemeFontColorInverse(); font-size:0.8em; font-family: @ssm.fetchThemeFont();">@ssm.params().asLogo()</span>
<i class="fa fa-@ssm.params().grs" aria-hidden="true"
style="font-size:0.9em; color: @ssm.fetchThemeFontColorInverse()"></i>
}
<span style="color:@ssm.fetchThemeFontColorInverse(); font-size:0.8em; font-family: @ssm.fetchThemeFont();">@ssm.params().asLogo()</span>
</div>
<div class="reveal">

View File

@ -4,10 +4,23 @@
<div class="container-fluid">
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<p class="navbar-text pull-left"><span class="octicon octicon-megaphone"
style="color: #e49436; font-weight:bold; font-size:0.9em"> GET THE WORD OUT!</span>
@if(offline) {
<p class="navbar-text pull-left"><span style="color: white; font-weight:bold; font-size: 1.3em"> @rndr.getGRS(rndr.params())</span>
</p>
@if(!offline) {
} else {
<li class="dropdown">
<a href="#" class="dropdown-toggle" style="font-size:1.3em; font-weight:bold" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">@rndr.getGRS(rndr.params()) <span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="dropdown-header">GitPitch Git Services</li>
<li role="separator" class="divider"></li>
@for(grs <- rndr.listGRS()) {
<li><a href='@rndr.pageLink(false, grs.getType())'>@grs.getName()</a></li>
}
</ul>
</li>
<li>
<a href="#popupTheme" role="button" data-toggle="modal-popover" data-placement="top"><i
class="fa fa-paint-brush" aria-hidden="true"> <span style="font-family: Helvetica Neue"

View File

@ -28,8 +28,7 @@
<ul class="nav navbar-nav">
@if(offline) {
<li style="font-size:1.2em; color:white"><a href="#">@rndr.user()</a></li>
<li style="font-size:1.2em; color:white" class="hidden-sd hidden-xs"><p class="navbar-text"
style="color:white">/</p></li>
<li style="font-size:1.2em; color:white" class="hidden-sd hidden-xs"><p class="navbar-text" style="color:white">/</p></li>
<li style="font-size:1.2em; color:white"><a href="#">@rndr.repo()</a></li>
<li><a href="#" style="font-size:1.2em;color:gray" class="hidden-sd hidden-xs">{
@rndr.displayLangOrBranch() }</a></li>
@ -39,8 +38,13 @@
class="octicon octicon-star"></span> Star @rndr.stargazers()</a></li>
<li class="visible-lg visible-md" style="font-size:1.1em; color:white"><a href="#"><span
class="octicon octicon-repo-forked"></span> Fork @rndr.forks()</a></li>
<li style="font-size:1.2em; color:white"><a href="#"><span class="mega-octicon octicon-mark-github"
style="font-size:1.3em"></span></a></li>
@if(rndr.params().grs.equals("github")) {
<li style="font-size:1.2em; color:white"><a href="#"><span class="mega-octicon octicon-mark-github" style="font-size:1.3em"></span></a></li>
} else {
<li style="font-size:1.2em; color:white"><a href="#"><span class="fa fa-@rndr.params().grs" aria-hidden="true" style="font-size:1.4em"></span></a></li>
}
} else {
<li style="font-size:1.2em; color:white"><a href="@rndr.orgHub()">@rndr.user()</a></li>
<li style="font-size:1.2em; color:white" class="hidden-sd hidden-xs"><p class="navbar-text"
@ -54,8 +58,13 @@
class="octicon octicon-star"></span> Star @rndr.stargazers()</a></li>
<li class="visible-lg visible-md" style="font-size:1.1em; color:white"><a href="@rndr.forkHub()"><span
class="octicon octicon-repo-forked"></span> Fork @rndr.forks()</a></li>
<li style="font-size:1.2em; color:white"><a href="@rndr.repoHub()"><span
class="mega-octicon octicon-mark-github" style="font-size:1.3em"></span></a></li>
<li style="font-size:1.2em; color:white"><a href="@rndr.repoHub()">
@if(rndr.params().grs.equals("github")) {
<span class="mega-octicon octicon-mark-github" style="font-size:1.3em"></span>
} else {
<span class="fa fa-@rndr.params().grs" aria-hidden="true" style="font-size:1.4em"></span>
}
</a></li>
}
</ul>
</div><!--/.nav-collapse -->

View File

@ -11,7 +11,7 @@
color: #e49436;
}
.navbar-inverse .navbar-nav > li > a:visited {
color: #white;
color: white;
}
.themes > a {
color: #e49436;

View File

@ -1,5 +1,5 @@
name := """server"""
version := "1.0"
version := "1.1"
organization := "com.gitpitch"
lazy val root = (project in file(".")).enablePlugins(PlayJava)

View File

@ -412,9 +412,48 @@ gitpitch {
}
}
git {
repo {
services = [
{
name = "GitHub"
type = "github"
site = "https://github.com/"
apibase = "https://api.github.com/"
// apitoken = "token your-github-access-token-here"
apitokenheader = "Authorization"
rawbase = "https://raw.githubusercontent.com/"
default = "true"
}
{
name = "GitLab"
type = "gitlab"
site = "https://gitlab.com/"
apibase = "https://gitlab.com/api/v3/"
// apitoken = "your-gitlab-access-token-here"
apitokenheader = "PRIVATE-TOKEN"
rawbase = "https://gitlab.com/"
default = "false"
}
{
name = "Bitbucket"
type = "bitbucket"
site = "https://bitbucket.org/"
apibase = "https://api.bitbucket.org/2.0/"
// apitoken = "your-bitbucket-access-token-here"
apitokenheader = "Authorization"
rawbase = "https://bitbucket.org/"
default = "false"
}
]
}
}
google {
analytics {
// token = "your-Google-Analytics-token"
// token = "your-google-analytics-token"
}
}

View File

@ -37,6 +37,9 @@
<logger name="com.gitpitch.filters" level="DEBUG" additivity="false">
<appender-ref ref="ASYNCSTDOUT"/>
</logger>
<logger name="com.gitpitch.git" level="DEBUG" additivity="false">
<appender-ref ref="ASYNCSTDOUT"/>
</logger>
<logger name="com.gitpitch.utils" level="DEBUG" additivity="false">
<appender-ref ref="ASYNCSTDOUT"/>
</logger>

View File

@ -9,10 +9,10 @@ GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset
GET /pitchme/gist/:gid com.gitpitch.controllers.PitchController.gist(gid:String)
# Serve PITCHME.pdf.
GET /pitchme/print/:user/:repo/:b/:t/PITCHME.pdf com.gitpitch.controllers.PitchController.print(user:String, repo:String, b:String, t:String, n:String ?= null)
GET /pitchme/print/:grs/:user/:repo/:b/:t/PITCHME.pdf com.gitpitch.controllers.PitchController.print(grs:String, user:String, repo:String, b:String, t:String, n:String ?= null)
# Serve PITCHME.zip.
GET /pitchme/offline/:user/:repo/:b/:t/PITCHME.zip com.gitpitch.controllers.PitchController.offline(user:String, repo:String, b:String, t:String, n:String ?= null)
GET /pitchme/offline/:grs/:user/:repo/:b/:t/PITCHME.zip com.gitpitch.controllers.PitchController.offline(grs:String, user:String, repo:String, b:String, t:String, n:String ?= null)
# Redirect to GitHub OAuth Access Request
# GET /pitchme/authreq com.gitpitch.controllers.AuthController.authreq()
@ -21,16 +21,16 @@ GET /pitchme/offline/:user/:repo/:b/:t/PITCHME.zip com.gitpitch.controlle
# GET /pitchme/authorized com.gitpitch.controllers.AuthController.authorized(code:String ?= null, state:String ?= null)
# Serve PITCHME.md markdown.
GET /pitchme/markdown/:user/:repo/:b/PITCHME.md com.gitpitch.controllers.PitchController.markdown(user:String, repo:String, b:String)
GET /pitchme/markdown/:grs/:user/:repo/:b/PITCHME.md com.gitpitch.controllers.PitchController.markdown(grs:String, user:String, repo:String, b:String)
# Serve PITCHME.md slideshow.
GET /pitchme/slideshow/:user/:repo/:b com.gitpitch.controllers.PitchController.slideshow(user:String, repo:String, b:String, t:String ?= null, n:String ?= null, fragments:String ?= null, offline:String ?= null)
GET /pitchme/slideshow/:grs/:user/:repo/:b com.gitpitch.controllers.PitchController.slideshow(grs:String, user:String, repo:String, b:String, t:String ?= null, n:String ?= null, fragments:String ?= null, offline:String ?= null)
# Serve PITCHME.md landing page.
GET /:user/:repo/:b com.gitpitch.controllers.PitchController.landing(user:String, repo:String, b:String, t:String ?= null, n:String?= null, offline:String ?= null)
GET /:user/:repo/:b com.gitpitch.controllers.PitchController.landing(user:String, repo:String, b:String, grs:String ?= null, t:String ?= null, n:String?= null, offline:String ?= null)
# Serve PITCHME.md landing page, short URI format.
GET /:user/:repo com.gitpitch.controllers.PitchController.landing(user:String, repo:String, b:String ?= null, t:String ?= null, n:String?= null, offline:String ?= null)
GET /:user/:repo com.gitpitch.controllers.PitchController.landing(user:String, repo:String, b:String ?= null, grs:String ?= null, t:String ?= null, n:String?= null, offline:String ?= null)
# Catch-all route redirect to website.
GET /*path com.gitpitch.controllers.PitchController.catchall(path:String)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -16,13 +16,13 @@ public class FunctionalTest {
private static final String LANDING_PITCH_FOUND = "/gitpitch/hello-world";
private static final String LANDING_PITCH_NOT_FOUND = "/gitpitch/hello-world/not-found";
private static final String SLIDESHOW_PITCH_FOUND =
"/pitchme/slideshow/gitpitch/hello-world/master";
"/pitchme/slideshow/github/gitpitch/hello-world/master";
private static final String SLIDESHOW_PITCH_NOT_FOUND =
"/pitchme/slideshow/gitpitch/hello-world/not-found";
"/pitchme/slideshow/github/gitpitch/hello-world/not-found";
private static final String MARKDOWN_PITCH_FOUND =
"/pitchme/markdown/gitpitch/hello-world/master/PITCHME.md";
"/pitchme/markdown/github/gitpitch/hello-world/master/PITCHME.md";
private static final String MARKDOWN_PITCH_NOT_FOUND =
"/pitchme/markdown/gitpitch/hello-world/not-found/PITCHME.md";
"/pitchme/markdown/github/gitpitch/hello-world/not-found/PITCHME.md";
private static final String UNSUPPORTED_ENDPOINT = "/unsupported";
private static final String INVALID_ENDPOINT = "/invalid/endpoint/";
private static final int SERVER_TEST_PORT = 3333;