問題場景
統計git上工程代碼行數,去除不必要的檔案,例如圖檔,idea的預設檔案,日志檔案等。
開發環境
idea+Java8+springboot2
分析
- 單個工程統計,腳本指令實作。
- Java代碼通過JGit實作與git通訊,通過周遊主分支最新的commit實作。
方案一實作
切換到工程目錄下後執行
方案二實作
引入maven依賴
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>5.4.0.201906121030-r</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>2.6.0</version>
</dependency>
/**
* 擷取某個commit代碼行數
* @param projectId gitlab工程id
* @param commitId commitId
* @param branchName 分支名
* @param postFix 檔案字尾過濾
* @return
*/
public long getAllFileLinesByCommitPostfix(Integer projectId, String commitId, String branchName, String postFix) throws GitAPIException {
Git git = null;
String path = null;
long size = 0;
try {
// 該方法自己實作,調用gitlab api即可
ProjectInfo projectInfo = getProjectNameById(projectId + "");
String gitUrl = projectInfo.getWebUrl();
String userPath = System.getProperties().getProperty("user.home");
path = userPath + "/data/" + projectInfo.getGzGroupName() + "/" + projectInfo.getProjectName() + "/" + System.currentTimeMillis();
git = getGitObject(gitUrl, path, branchName);
TreeWalk treeWalk = new TreeWalk(git.getRepository());
RevWalk walk = new RevWalk(git.getRepository());
RevCommit commit = walk.parseCommit(git.getRepository().resolve(commitId));
treeWalk.addTree(commit.getTree());
treeWalk.setRecursive(true);
MutableObjectId id = new MutableObjectId();
while (treeWalk.next()) {
treeWalk.getObjectId(id, 0);
String filePath = treeWalk.getPathString();
if (filePath.startsWith(".") || filePath.startsWith("med/")
|| filePath.contains("target/classes") || filePath.endsWith("pom.xml")
|| filePath.endsWith(".log") || filePath.endsWith(".iml")) {
continue;
}
if (StringUtils.isNotBlank(postFix) && !filePath.endsWith(postFix)) {
continue;
}
String absPath = path + "/" + filePath;
// System.out.println("absPath: " + absPath);
// filter image
File file = new File(absPath);
long lines = 0;
try (InputStream in = new FileInputStream(file)) {
FileType fileType = FileUtil.getFileType(in);
if (fileType != null) {
continue;
}
lines = Files.lines(Paths.get(file.getPath())).count();
// System.out.println(filePath + " -> " + lines);
} catch (UncheckedIOException e) {
log.error("encode not match for utf-8, absPath: {}, msg: {}", absPath, e.getMessage());
}
size += lines;
}
} catch (IOException e) {
log.error("error:", e);
} finally {
//删除前關閉
if (git != null) {
git.getRepository().close();
}
// 删除方法
this.deleteFile(path);
}
return size;
}
/**
* 擷取Git對象
*/
private Git getGitObject(String gitUrl, String mkdir, String sourceBranch) throws GitAPIException {
Git git = null;
try {
// token自己申請替換
git = Git.cloneRepository()
.setURI(gitUrl)
.setDirectory(new File(mkdir))
.setCloneAllBranches(true)
.setBranch(URLEncoder.encode(sourceBranch, "UTF-8"))
.setCredentialsProvider(new UsernamePasswordCredentialsProvider("PRIVATE-TOKEN", "xxx"))
.call();
} catch (UnsupportedEncodingException e) {
log.error("git clone 失敗,{}", e.getMessage());
}
return git;
}
private void deleteFile(String dir){
try {
FileDeleteStrategy.FORCE.delete(new File(dir));
} catch (NoSuchFileException e) {
log.info("删除曆史git檔案時,未找到,{}", e.getMessage());
}catch (IOException e){
log.error("删除git曆史檔案失敗,{}", e.getMessage());
}
}
import lombok.Getter;
@Getter
public enum FileType {
/**
* JPEG
*/
JPEG("FFD8FF", "jpg"),
/**
* PNG
*/
PNG("89504E47", "png"),
/**
* GIF
*/
GIF("47494638", "gif"),
/**
* ICO
*/
ICO("0000010000", "ico"),
/**
* TIFF
*/
TIFF("49492A00"),
/**
* Windows bitmap
*/
BMP("424D"),
/**
* CAD
*/
DWG("41433130"),
/**
* Adobe photoshop
*/
PSD("38425053"),
/**
* Rich Text Format
*/
RTF("7B5C727466"),
/**
* XML
*/
XML("3C3F786D6C"),
/**
* HTML
*/
HTML("68746D6C3E"),
/**
* Outlook Express
*/
DBX("CFAD12FEC5FD746F "),
/**
* Outlook
*/
PST("2142444E"),
/**
* doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db
*/
OLE2("0xD0CF11E0A1B11AE1"),
/**
* Microsoft Word/Excel
*/
XLS_DOC("D0CF11E0"),
/**
* Microsoft Access
*/
MDB("5374616E64617264204A"),
/**
* Word Perfect
*/
WPB("FF575043"),
/**
* Postscript
*/
EPS_PS("252150532D41646F6265"),
/**
* Adobe Acrobat
*/
PDF("255044462D312E"),
/**
* Windows Password
*/
PWL("E3828596"),
/**
* ZIP Archive
*/
ZIP("504B0304"),
/**
* ARAR Archive
*/
RAR("52617221"),
/**
* WAVE
*/
WAV("57415645"),
/**
* AVI
*/
AVI("41564920"),
/**
* Real Audio
*/
RAM("2E7261FD"),
/**
* Real Media
*/
RM("2E524D46"),
/**
* Quicktime
*/
MOV("6D6F6F76"),
/**
* Windows Media
*/
ASF("3026B2758E66CF11"),
/**
* MIDI
*/
MID("4D546864");
private String value;
private String ext = "";
FileType(String value) {
this.value = value;
}
FileType(String value, String ext) {
this(value);
this.ext = ext;
}
}
import java.io.IOException;
import java.io.InputStream;
/**
* 〈〉
*
* @author yangyouxing
* @create 2020-07-24
* @since 1.0.0
*/
public final class FileUtil {
private FileUtil() {
}
/**
* 擷取檔案類型
* @param is
* @return
* @throws IOException
*/
public static FileType getFileType(InputStream is) throws IOException {
byte[] src = new byte[28];
is.read(src, 0, 28);
StringBuilder stringBuilder = new StringBuilder();
for (byte b : src) {
int v = b & 0xFF;
String hv = Integer.toHexString(v).toUpperCase();
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
FileType[] fileTypes = FileType.values();
for (FileType fileType : fileTypes) {
if (stringBuilder.toString().startsWith(fileType.getValue())) {
return fileType;
}
}
return null;
}
}