程序输出代码commit-ID


1、个人方法

1.1 获取commit-id

      采用git log获取代码commit-id字符串,记为version_str

1.2 makefile定义宏

      如定义1个名为VERSION的自定义宏,然后将version_str值赋给该宏

1.3 代码改动

      在代码内利用makefile内定义的宏VERSION

#ifdef VERSION
...
#endif

1.4 范例

/*----------------makefile---------------*/
CC=g++
	CFLAGS+=-D VERSION=\"XXX\"
tt:main.cpp
	$(CC) $(CFLAGS) $^ -o $@
%.o:%.cpp
	$(CC) $(CFLAGS) -c %<
PHONY:clean
clean:
	rm -rf *.o tt

注意:宏VERSION=\"XXX\",输出字符串XXX;

/*----------------mainc.cpp---------------*/
#include <iostream>
using namespace std;
int main()
{
 //
#ifdef VERSION
 cout<<"++++++++++++++++++++++"<<endl;
 cout<<VERSION<<endl;
#endif
 return 1;
}

2、别人方法

2.1 CMake获取git commit-Id

  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(test)
set(SRCS main.cpp)

# 执行git命令,并把结果重定向到自定义变量(此处是我的变量<GIT_VERSION>)。
execute_process(
	COMMAND	git log -1 --format=%H 		//git 命令
	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 
	OUTPUT_VARIABLE GIT_VERSION
)
execute_process(
	COMMAND git remote -v 				//git 命令
	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 
	OUTPUT_VARIABLE GIT_REMOTE_PATH
)

# 对得到的结果进行处理,尤其注意 \n,\t,\r之类的特殊字符,在cmake时没问题,但是生成的.cmake文件有问题,导致make出错。
string (REGEX REPLACE ".*\t| .*" "" GIT_PATH ${GIT_REMOTE_PATH})
string (REGEX REPLACE "[\n\t\r]" "" GIT_VERSION ${GIT_VERSION})

# 增加编译选项,把宏导入源码
add_definitions( -DGIT_VERSION=\"${GIT_VERSION}\")
add_definitions( -DGIT_PATH=\"${GIT_PATH}\")
add_executable(app ${SRCS})
  • main.cpp
#include <iostream>
using namespace std;

int main(){
	cout << "Hello world\n";
	cout << "[GitPath] " << GIT_PATH << endl;			//使用CMakeLists.txt中定义的变量,详情请看该文最下方。
	cout << "[GitVersion] " << GIT_VERSION << endl;
	cout << "[BuildDate] " << __DATE__ << endl;
	cout << "[BuildTime] " << __TIME__ << endl;
	return 0;
}
  • 效果
    在这里插入图片描述

2.2 Makefile 获取git commit-ID

  • Makefile
TARGET := test
CPP_SRCS += main.cpp
C_SRCS = main.c
CC := g++
C = gcc

#获取GIT版本信息和路径(在代码中使用宏GIT_VERSION和GIT_PATH)
GIT_SHA = $(shell git rev-list HEAD | awk 'NR==1')
GIT_SEQ = $(shell git rev-list HEAD | wc -l)
GIT_VER_INFO = $(GIT_SHA)-$(GIT_SEQ)
GIT_SVR_PATH = $(shell git remote -v | awk 'NR==1' | sed 's/[()]//g' | sed 's/\t/ /g' |cut -d " " -f2)
##定义GIT版本信息宏和路径宏,CFLAGS是编译选项变量
ifneq ($(GIT_VER_INFO),)
CFLAGS += -DGIT_VERSION=\"$(GIT_VER_INFO)\"
else
CFLAGS += -DGIT_VERSION=\"unknown\"
endif
CFLAGS += -DGIT_PATH=\"$(GIT_SVR_PATH)\"

debug :
	@echo $(CFLAGS)

m_cpp : $(CPP_SRCS)
	$(CC) $(CFLAGS) -o $@ $^

m_c : $(C_SRCS)
	$(C) $(CFLAGS) -o $@ $^

clean :
	rm m_cpp m_c test main
  • main.cpp
#include <iostream>
using namespace std;

int main(){
	cout << "Hello world\n";
	cout << "[GitPath] " << GIT_PATH << endl;
	cout << "[GitVersion] " << GIT_VERSION << endl;
	cout << "[BuildDate] " << __DATE__ << endl;
	cout << "[BuildTime] " << __TIME__ << endl;
	cout << "End\n";
	return 0;
}
  • main.c
#include <stdio.h>
int main()
{
	printf("GitPath[%s],GitVersion[%s],BuildTime[%s%s]\n",GIT_PATH,GIT_VERSION,__DATE__,__TIME__);
	return 0;
}
以下是一个示例程序,可以实现获取同一个 Java 类中不同次代码提交变更的方法,以及将变更代码解析对应的类文件及内部的方法并存储: ```java import org.eclipse.jgit.api.Git; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.PathFilter; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; public class JavaCodeChanges { public static void main(String[] args) throws IOException { String repoDir = "/path/to/your/repo"; // Git 仓库的本地路径 String filePath = "src/main/java/YourClass.java"; // Java 类文件的路径 try (Git git = Git.open(Paths.get(repoDir))) { Iterable<RevCommit> commits = git.log().addPath(filePath).call(); Map<String, Set<String>> methodsMap = new HashMap<>(); // 保存方法名的映射 RevCommit prevCommit = null; for (RevCommit commit : commits) { if (prevCommit != null) { RevWalk walk = new RevWalk(git.getRepository()); // 获取两个提交之间的差异 ObjectReader reader = git.getRepository().newObjectReader(); CanonicalTreeParser oldTreeIter = new CanonicalTreeParser(); oldTreeIter.reset(reader, prevCommit.getTree()); CanonicalTreeParser newTreeIter = new CanonicalTreeParser(); newTreeIter.reset(reader, commit.getTree()); List<DiffEntry> diffs = git.diff() .setOldTree(oldTreeIter) .setNewTree(newTreeIter) .setPathFilter(PathFilter.create(filePath)) .call(); // 解析差异中的变更代码 for (DiffEntry diff : diffs) { String[] lines = git.show().setPath(diff.getNewPath()).call().split("\n"); for (String line : lines) { if (line.matches("^\\s*public.*\\(.*\\)\\s*\\{\\s*$")) { String method = line.replaceFirst("^\\s*public\\s*", "") .replaceFirst("\\(.*\\)\\s*\\{\\s*$", ""); // 将方法名及对应的提交 ID 添加到映射中 if (!methodsMap.containsKey(method)) { methodsMap.put(method, new HashSet<>()); } methodsMap.get(method).add(commit.getName()); } } } walk.dispose(); } prevCommit = commit; } // 解析每个提交对应的类文件,并提取其中的方法 for (Map.Entry<String, Set<String>> entry : methodsMap.entrySet()) { String method = entry.getKey(); Set<String> commitIds = entry.getValue(); for (String commitId : commitIds) { Path classFilePath = Paths.get(repoDir, ".git", "objects", commitId.substring(0, 2), commitId.substring(2)); byte[] classFileData = git.getRepository().open(classFilePath).getBytes(); byte[] decompressedData = org.eclipse.jgit.util.IO.readFully(classFileData); byte[] classBytes = org.eclipse.jgit.lib.Constants.encodedTypeString(org.eclipse.jgit.lib.Constants.OBJ_BLOB).getBytes(StandardCharsets.US_ASCII); byte[] allBytes = new byte[classBytes.length + decompressedData.length]; System.arraycopy(classBytes, 0, allBytes, 0, classBytes.length); System.arraycopy(decompressedData, 0, allBytes, classBytes.length, decompressedData.length); // 解析类文件中的方法 ClassReader classReader = new ClassReader(allBytes); ClassNode classNode = new ClassNode(); classReader.accept(classNode, 0); for (MethodNode methodNode : classNode.methods) { if (methodNode.name.equals(method)) { // 保存方法名及对应的类名和提交 ID Path outputDir = Paths.get("output"); Files.createDirectories(outputDir); Path outputFile = outputDir.resolve(method + ".txt"); String output = classNode.name + " (" + commitId + ")"; Files.write(outputFile, Collections.singleton(output), StandardCharsets.UTF_8); } } } } } } } ``` 这个程序使用 JGit 库来访问 Git 仓库,并使用 `git diff` 命令来比较两个提交之间 Java 类文件的差异。它会输出所有变更过的方法名,并将变更代码解析对应的类文件及内部的方法,并存储到一个文本文件中。你需要替换 `repoDir` 和 `filePath` 变量为你自己的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值