blob: 5c8d65f2b70293d9f69d237dd950a074eaa04162 [file] [log] [blame]
Dave Borowitz9de65952012-08-13 16:09:45 -07001// Copyright 2012 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.gitiles;
16
17import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
18
19import com.google.common.collect.Maps;
20
21import org.eclipse.jgit.diff.RawText;
22import org.eclipse.jgit.errors.LargeObjectException;
23import org.eclipse.jgit.errors.MissingObjectException;
24import org.eclipse.jgit.lib.Constants;
25import org.eclipse.jgit.lib.ObjectId;
26import org.eclipse.jgit.lib.ObjectLoader;
27import org.eclipse.jgit.revwalk.RevWalk;
28import org.eclipse.jgit.util.RawParseUtils;
29
30import java.io.IOException;
31import java.util.Map;
32
33/** Soy data converter for git blobs. */
34public class BlobSoyData {
35 /**
36 * Maximum number of bytes to load from a supposed text file for display.
37 * Files larger than this will be displayed as binary files, even if the
38 * contents was text. For example really big XML files may be above this limit
39 * and will get displayed as binary.
40 */
41 private static final int MAX_FILE_SIZE = 10 << 20;
42
43 private final GitilesView view;
44 private final RevWalk walk;
45
46 public BlobSoyData(RevWalk walk, GitilesView view) {
47 this.view = view;
48 this.walk = walk;
49 }
50
51 public Map<String, Object> toSoyData(ObjectId blobId)
52 throws MissingObjectException, IOException {
53 return toSoyData(null, blobId);
54 }
55
56 public Map<String, Object> toSoyData(String path, ObjectId blobId)
57 throws MissingObjectException, IOException {
58 Map<String, Object> data = Maps.newHashMapWithExpectedSize(4);
59 data.put("sha", ObjectId.toString(blobId));
60
61 ObjectLoader loader = walk.getObjectReader().open(blobId, Constants.OBJ_BLOB);
62 String content;
63 try {
64 byte[] raw = loader.getCachedBytes(MAX_FILE_SIZE);
65 content = !RawText.isBinary(raw) ? RawParseUtils.decode(raw) : null;
66 } catch (LargeObjectException.OutOfMemory e) {
67 throw e;
68 } catch (LargeObjectException e) {
69 content = null;
70 }
71
72 data.put("data", content);
73 if (content != null) {
74 data.put("lang", guessPrettifyLang(path, content));
75 } else if (content == null) {
76 data.put("size", Long.toString(loader.getSize()));
77 }
78 if (path != null && view.getRevision().getPeeledType() == OBJ_COMMIT) {
79 data.put("logUrl", GitilesView.log().copyFrom(view).toUrl());
Dave Borowitz6ec0c872014-01-29 13:59:37 -080080 data.put("blameUrl", GitilesView.blame().copyFrom(view).toUrl());
Dave Borowitz9de65952012-08-13 16:09:45 -070081 }
82 return data;
83 }
84
85 private static String guessPrettifyLang(String path, String content) {
86 if (content.startsWith("#!/bin/sh") || content.startsWith("#!/bin/bash")) {
87 return "sh";
88 } else if (content.startsWith("#!/usr/bin/perl")) {
89 return "perl";
90 } else if (content.startsWith("#!/usr/bin/python")) {
91 return "py";
92 } else if (path == null) {
93 return null;
94 }
95
96 int slash = path.lastIndexOf('/');
97 int dot = path.lastIndexOf('.');
98 String lang = ((0 < dot) && (slash < dot)) ? path.substring(dot + 1) : null;
99 if ("txt".equalsIgnoreCase(lang)) {
100 return null;
101 } else if ("mk".equalsIgnoreCase(lang)) {
102 return "sh";
103 } else if ("Makefile".equalsIgnoreCase(path)
104 || ((0 < slash) && "Makefile".equalsIgnoreCase(path.substring(slash + 1)))) {
105 return "sh";
106 } else {
107 return lang;
108 }
109 }
110}