java通過代碼實(shí)現(xiàn)創(chuàng)建項(xiàng)目,提交項(xiàng)目等功能

ps:首先要講一下前提包蓝。用的是gitlab驶社。然后因?yàn)樾枨笤颍M麑?shí)現(xiàn)的是用戶的某個(gè)操作自動(dòng)創(chuàng)建一個(gè)git的工作空間测萎,然后用戶可以配置一些東西亡电,會(huì)用代碼的形式以文件的形式push到git。最終可以通過某種方式直接將這個(gè)項(xiàng)目再k8s中運(yùn)行起來硅瞧。
另外希望可以將git項(xiàng)目中的文件和最后修改時(shí)間以列表的形式返回(因?yàn)橛行┤瞬幌虢ogit權(quán)限逊抡,但是給提供查看文件更新時(shí)間的功能)。

我負(fù)責(zé)的是簡(jiǎn)單的創(chuàng)建項(xiàng)目和push,展示文件列表冒嫡。因?yàn)槠鋵?shí)這個(gè)功能不是很常見拇勃,所以寫的時(shí)候沒有拿來主義,自己調(diào)試了好久孝凌,所以這里簡(jiǎn)單記錄下:
一共分為三個(gè)接口:
create空git項(xiàng)目
push項(xiàng)目
拉取項(xiàng)目所有文件并獲取最后修改時(shí)間

假設(shè)我有了有權(quán)限的token,申請(qǐng)方式是這樣的:
注意一點(diǎn)方咆,不是在git中可以crud就是有權(quán)限,可能git頁(yè)面和接口的權(quán)限是不一樣的蟀架,所以要在接口中有這個(gè)setting的賬號(hào)申請(qǐng)的token才生效瓣赂。


有權(quán)限的賬號(hào)

然后有了token以后,進(jìn)行創(chuàng)建(注意projectName是要?jiǎng)?chuàng)建的名稱片拍,apiUrl 是git地址煌集,namespace_id是想要?jiǎng)?chuàng)建的目錄的id):

    private static String token = "xx";
    public static void createProject(String projectName){
        try {
            HttpClient httpClient = HttpClients.createDefault();
            // 構(gòu)建 API 請(qǐng)求 URL
            String apiUrl = "https://gitlab.xx.xxx.com/api/v4/projects";
            // 構(gòu)建請(qǐng)求體 JSON 數(shù)據(jù)
            String requestBody = "{\"name\": \"" + projectName + "\",\"namespace_id\": 62296}";

            // 創(chuàng)建 POST 請(qǐng)求
            HttpPost httpPost = new HttpPost(apiUrl);
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Private-Token", token);
            httpPost.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON));

            // 發(fā)送請(qǐng)求并獲取響應(yīng)
            HttpResponse response = httpClient.execute(httpPost);
            System.out.println(response);
            HttpEntity entity = response.getEntity();
            // 處理響應(yīng)
            if (entity != null) {
                String responseString = entity.toString();
                System.out.println(responseString);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

提交文件:

public static String createAndAddFileToGitRepo(CamelProjectEntity camelProjectEntity,List<CamelDataEntity> list) {
        try {
            // Clone the Git repository
            File localPath = File.createTempFile("temp-git-repo", "");
            localPath.delete();
            CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider("userName", "password");
            Git git = Git.cloneRepository()
                    .setURI(camelProjectEntity.getGitAddress())
                    .setCredentialsProvider(credentialsProvider)
                    .setDirectory(localPath)
                    .call();
            // Create the file
            for (CamelDataEntity c : list) {
                String fileName = c.getName()+".yml";
                String content = c.getYml();
                // Create the file
                File file = new File(localPath.getPath() + File.separator + fileName);
                FileWriter writer = new FileWriter(file);
                writer.write(content);
                writer.close();
                // Add the file to the Git repository
                git.add()
                        .addFilepattern(fileName)
                        .call();
            }
            // Commit the changes
            git.commit()
                    .setMessage("Add files")
                    .call();

            // Push the changes to the remote repository
            git.push()
                    .setCredentialsProvider(credentialsProvider)
                    .call();
            // Clean up
            git.close();
            localPath.deleteOnExit();
            return "推送成功";
        }catch (Exception e){
            e.printStackTrace();
            return "推送失敗";
        }

    }

最后一個(gè)方法比較麻煩,我直接附上完整的代碼:

package com.lenovo.common.utils;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryBuilder;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.util.io.DisabledOutputStream;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;

public class GitLastCommitTime {

    public static boolean deleteFile(String path) {
        File file = new File(path);
        if (!file.exists()) {
            System.out.println("File or directory does not exist.");
            return false;
        }
        if (file.isDirectory()) {
            // 如果是目錄捌省,則遞歸刪除其中的文件和子目錄
            File[] files = file.listFiles();
            if (files != null) {
                for (File subFile : files) {
                    deleteFile(subFile.getAbsolutePath());
                }
            }
        }
        // 刪除文件或空目錄
        return file.delete();
    }

    public static   Map<String, Object>  git(String gitRepoUrl){
        String username = "username ";
        String password = "password ";
        String name = gitRepoUrl;
        deleteFile(name);
        try (Git git = cloneRepository(gitRepoUrl, username, password)) {
            Repository repo = createRepository(git.getRepository());
            Map<String, Date> fileLastCommitTimeMap = getFileLastCommitTimeMap(repo);
            Iterator<Map.Entry<String, Date>> iterator = fileLastCommitTimeMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Date> entry = iterator.next();
                if (entry.getKey().contains(".git")) {
                    iterator.remove();
                }
            }
            Map<String, String> folderContentMap = readFolderContents(name);
            Map<String, Object> res = convertToTree(fileLastCommitTimeMap,name);
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static Map<String, String> readFolderContents(String folderPath) {
        Map<String, String> folderContentMap = new HashMap<>();
        File folder = new File(folderPath);

        if (!folder.isDirectory()) {
            throw new IllegalArgumentException("Specified path is not a valid folder.");
        }

        File[] files = folder.listFiles();

        for (File file : files) {
            if (file.isFile() && (file.getName().endsWith("xslt") || file.getName().endsWith("dfdl"))) {
                try {
                    String content = new String(Files.readAllBytes(file.toPath()));
                    folderContentMap.put(file.getName(), content);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (file.isDirectory()) {
                folderContentMap.putAll(readFolderContents(file.getPath()));
            }
        }
        return folderContentMap;
    }

    public static Map<String, Object> convertToTree(Map<String, Date> fileLastModifiedMap,String name) {
        Map<String, Object> root = new HashMap<>();
        root.put("files", new HashMap<>());
        root.put("name", name);
        root.put("subfolders", new ArrayList<>());

        for (String filePath : fileLastModifiedMap.keySet()) {
            String[] folders = filePath.split("/");

            Map<String, Object> currentNode = root;
            for (int i = 0; i < folders.length - 1; i++) {
                String folder = folders[i];
                List<Map<String, Object>> subfolders = (List<Map<String, Object>>) currentNode.get("subfolders");
                Optional<Map<String, Object>> optionalFolder = subfolders.stream()
                        .filter(f -> f.get("name").equals(folder))
                        .findFirst();

                if (optionalFolder.isPresent()) {
                    currentNode = optionalFolder.get();
                } else {
                    Map<String, Object> newFolder = new HashMap<>();
                    newFolder.put("files", new HashMap<>());
                    newFolder.put("name", folder);
                    newFolder.put("subfolders", new ArrayList<>());

                    subfolders.add(newFolder);
                    currentNode = newFolder;
                }
            }

            String file = folders[folders.length - 1];
            Map<String,String> files = (Map<String,String>) currentNode.get("files");
            files.put(file,new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(fileLastModifiedMap.get(filePath)));
        }

        return root;
    }

    private static Git cloneRepository(String gitRepoUrl, String username, String password) throws GitAPIException {
        return Git.cloneRepository()
                .setURI(gitRepoUrl)
                .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password))
                .call();
    }
    private static Repository createRepository(org.eclipse.jgit.lib.Repository jGitRepo) throws Exception {
        RepositoryBuilder builder = new RepositoryBuilder();
        builder.setGitDir(jGitRepo.getDirectory());
        builder.readEnvironment();

        return builder.build();
    }

    private static Map<String, Date> getFileLastCommitTimeMap(Repository repository) throws IOException {
        Map<String, Date> fileLastCommitTimeMap = new HashMap<>();

        try {
            org.eclipse.jgit.api.Git git = new org.eclipse.jgit.api.Git(repository);
            RevWalk revWalk = new RevWalk(repository);
            Iterable<RevCommit> commits = git.log().all().call();

            for (RevCommit commit : commits) {
                RevCommit parentCommit = null;

                if (commit.getParentCount() > 0) {
                    parentCommit = revWalk.parseCommit(commit.getParent(0).getId());
                }

                List<DiffEntry> diffs = getDiffEntries(repository, parentCommit, commit);

                for (DiffEntry diff : diffs) {
                    String filePath = diff.getNewPath();
                    Date lastCommitTime = fileLastCommitTimeMap.getOrDefault(filePath, new Date(0));
                    Date commitTime = new Date(commit.getCommitTime() * 1000L);

                    if (commitTime.after(lastCommitTime)) {
                        fileLastCommitTimeMap.put(filePath, commitTime);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return fileLastCommitTimeMap;
    }
    private static List<DiffEntry> getDiffEntries(Repository repository, RevCommit parentCommit, RevCommit commit) throws IOException {
        DiffFormatter diffFormatter = new DiffFormatter(DisabledOutputStream.INSTANCE);
        diffFormatter.setRepository(repository);
        diffFormatter.setDetectRenames(true);

        return diffFormatter.scan(parentCommit != null ? parentCommit.getTree() : null, commit.getTree());
    }

    class FileCommitInfo {
        private String filePath;
        private Date lastCommitTime;

        public FileCommitInfo(String filePath, Date lastCommitTime) {
            this.filePath = filePath;
            this.lastCommitTime = lastCommitTime;
        }

        public String getFilePath() {
            return filePath;
        }

        public Date getLastCommitTime() {
            return lastCommitTime;
        }
    }
}

最后這個(gè)方法因?yàn)椴襟E比較多苫纤,我全貼出來修改敏感詞的,所以如果跑不通自己調(diào)試下就行了

本篇筆記就記到這里纲缓,如果稍微幫到你了記得點(diǎn)個(gè)喜歡點(diǎn)個(gè)關(guān)注~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卷拘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子祝高,更是在濱河造成了極大的恐慌栗弟,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件工闺,死亡現(xiàn)場(chǎng)離奇詭異乍赫,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)陆蟆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門耿焊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人遍搞,你說我怎么就攤上這事罗侯。” “怎么了溪猿?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵钩杰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我诊县,道長(zhǎng)讲弄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任依痊,我火速辦了婚禮避除,結(jié)果婚禮上怎披,老公的妹妹穿的比我還像新娘。我一直安慰自己瓶摆,他們只是感情好凉逛,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著群井,像睡著了一般状飞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上书斜,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天诬辈,我揣著相機(jī)與錄音,去河邊找鬼荐吉。 笑死焙糟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的样屠。 我是一名探鬼主播穿撮,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼瞧哟!你這毒婦竟也來了混巧?” 一聲冷哼從身側(cè)響起枪向,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤勤揩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后秘蛔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體陨亡,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年深员,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了负蠕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倦畅,死狀恐怖遮糖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叠赐,我是刑警寧澤欲账,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站芭概,受9級(jí)特大地震影響赛不,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜罢洲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一踢故、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦殿较、人聲如沸耸峭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)抓艳。三九已至,卻和暖如春帚戳,著一層夾襖步出監(jiān)牢的瞬間玷或,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工片任, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留偏友,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓对供,卻偏偏與公主長(zhǎng)得像位他,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子产场,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容