CS61B sp21fall Project02 Gitlet

Project02 Gitlet

  • 一、项目简介
  • 二、Git和Gitlet
    • 2.1 Git简介
    • 2.2 Gitlet简介
  • 三、框架设计
    • 3.1 Blobs
    • 3.2 Trees
    • 3.3 Commits
  • 四、.Gitlet文件结构设计
    • 4.1 .git文件架构
      • 4.1.1 重点介绍
        • index(VSCode中无法查看,会乱码)
        • objects(VSCode中无法查看,会乱码)
      • 4.1.2 其他文件大杂烩
    • 4.2 Gitlet文件架构设计
  • 五、项目文件设计
    • Repository类
      • init函数
      • add函数
      • commit函数
      • rm函数
      • log函数
      • global_log函数
      • find函数
      • status函数
      • checkout部分综合代码
      • branch函数
      • rm_branch函数
      • reset函数
      • merge函数

一、项目简介

这个项目将会带着我们一同手写实现一个Git版本管理工具,事件性和趣味性非常强,想象一下自己可以使用自己写的代码管理工具Gitlet,想想都爽。

二、Git和Gitlet

2.1 Git简介

  1. 保存整个文件目录的内容。在git中,这被称为提交(git commit + git push),而保存的内容本身被称为提交。
  2. 还原一个或多个文件的版本或整个提交。在git中,这称为签出那些文件或提交的文件。
  3. 查看备份的历史记录。在git中,您可以在称为日志的东西中查看此历史(简称开发历史,同时起到还原的作用)。
  4. 维护相关的提交序列,称为分支(branch)。
  5. 将一个分支中的更改合并到另一个分支中(简单理解就是将不同版本的代码进行合并)。
  6. 不仅支持历史版本的修改,还能支持形式上的不同实现方案(Plan A B C D)同时推进。

2.2 Gitlet简介

  1. Gitlet支持多版本多分枝开发。
  2. Gitlet不支持删除commit,这样设计的目的是尽可能保证各个历史版本的完整性。
  3. Gitlet的结构比较像树形结构,但是Gitlet仅仅支持两个parents的树形结构。
  4. GItlet更像是一个本地Git版本管理工具,将代码推送到远程分支的功能可以自己感兴趣进行添加,在我的项目实现里面我添加了这个功能,因为是Git的忠实信徒(doge)。

三、框架设计

3.1 Blobs

将代码还有文件内容保存到一个一个blobs里面,不同版本的文件只需要通过指针指向该版本对应条件下存在的文件就可以实现版本回退和更换,CS61B的助教课中的Assistant画了一幅非常生动的图:
在这里插入图片描述
这幅图就非常直观表示出了不同分支内容和blobs之间的关系,图片中红色的就是blobs,对于项目中的每一个文件,都有一个blob保存这个文件。

3.2 Trees

因为要支持多版本的文件更新,所以使用树形结构,如果仅仅使用链表只能支持单个分支的形式。
在这里插入图片描述

3.3 Commits

将元数据、日志信息(正常commit -m后面加的东西)、还有相关指针信息
在这里插入图片描述
这张图我感觉很好地展示了commit和blobs之间的关系,可以看到blobs是真正存储数据的部分,commit通过存储对于数据存储块的引用(在C语言中就是指针)来实现版本追踪,同时很大程度上节省了空间,不用每次commit都将所有的数据单独保存成一个快照。

四、.Gitlet文件结构设计

4.1 .git文件架构

这里.Gitlet的设计可以参考.git文件夹的设计,在VSCode中打开隐藏的.git文件夹查看结构:
在这里插入图片描述
借用阿里的.git文件架构介绍:
在这里插入图片描述
如果想要一个纯净的.git文件参考一下用来写init函数,可以在powershell中找一个文件夹执行git init,于是乎得到以下文件:
在这里插入图片描述

4.1.1 重点介绍

index(VSCode中无法查看,会乱码)

保存暂存区的内容,可以简单理解成一个本地的temp文件,在推送至远端或者进行快照之前可供修改的部分

objects(VSCode中无法查看,会乱码)

这个是实现的重点,包含三个内容:

  • commits:元数据,commit指针以及整体commit的维护
  • trees:各个commit版本文件的存储结构(数据结构)
  • blobs:数据块

这个部分在GItlet中使用了Java的面向对象编程中常用的对象序列化和对象反序列化进行

4.1.2 其他文件大杂烩

  • COMMIT_EDITMSG:commit修改的最新的相关信息

    这里输出的commit内容刚好跟我最近一次提交的信息对应:
    在这里插入图片描述

  • config:设置远程仓库地址以及远程仓库分支、本地仓库分支

在这里插入图片描述

  • HEAD:保存了本地仓库的分支指针位置,在这个仓库中是master
    在这里插入图片描述
  • ORIG_HEAD:用哈希的方法随机生成的唯一标识码
    在这里插入图片描述
  • log :保存日志信息相关内容
    • HEAD:保存所有的头部指针信息
      在这里插入图片描述
      这里的matster文件保存了所有master分支提交的信息在这里插入图片描述
    • refs:保存本地分支和远程分支对应关系
      在这里插入图片描述

4.2 Gitlet文件架构设计

  • objects 文件夹:存储commit和blob对象,数据结构是tree(使用hashcode作为文件名)
    • commits文件夹:存储每一次commit信息
    • blobs文件夹:存储数据块
  • commit 文件:用sha1编码保存对commit的引用
  • blob文件:用sha1编码·1保存对blob的引用
  • remotes 存储远端分支内容,用于远程推送
  • HEAD文件: 存储当前分支的名称,默认为master分支,在init的时候生成
  • staging 存储缓存区内容(以Stage class的形式存储blob)
  • removedStage 存储被rm的文件(以Stage class的形式存储)

五、项目文件设计

在这里插入图片描述

  • Utils文件中是用于实现生成sha1标签值、对象序列化和反序列化、使用到的数据结构、常用的IO操作的辅助函数
  • Repository中定用于初始化的时候定义Gitlet项目文件夹的架构和文件初始化。
  • Commit中定义了git中比较重要的一个类commit的应用。

tips:

  1. 序列化的时间不能由于对象的内容大小而变化。

Repository类

init函数

public void init() {
        //create a new .gitlet directory
        if (GITLET_DIR.exists()) {
            System.out.println("A Gitlet version-control system already exists in the current directory.");
            return;
        } else {
            GITLET_DIR.mkdir();
            // set the visibility of the .gitlet directory to hidden
            DosFileAttributeView fileAttributeView = Files.getFileAttributeView(GITLET_DIR.toPath(), DosFileAttributeView.class);
            try {
                fileAttributeView.setHidden(true);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //get the current time
            long time = System.currentTimeMillis();
            //change the type of the time to a string
            String timestamp = String.valueOf(time);
            //create the initial commit
            Commit initialCommit = new Commit("initial commit", null,timestamp, null);
            //set the branch to master by defult
            branch = "master";
            //create object area for commits areas
            File object = join(GITLET_DIR, "object");
            //create subdirectories for commits areas and blobs
            File commit = join(object, "commit");
            //create subdirectories for blobs areas
            File blob = join(object, "blob");
            //create head area for commits areas
            File head = join(GITLET_DIR, "HEAD");
            //init the head to master
            writeContents(head, "master");
            //create staging area for commits
            File staging = join(GITLET_DIR, "staging");
            //create the files above
            object.mkdir();
            commit.mkdir();
            blob.mkdir();
            staging.mkdir();
        }

    }
  1. 判断当前文件夹下是否存在.gitlet仓库,如果没有就新建一个,如果有就提示已经存在。
  2. 创建commit文件夹和blob文件夹,同时初始化一个initial commit对象到文件并保存到commit文件夹下
  3. 创建一个staging区域用于暂存commit的内容。

add函数

//add a copy of the files as currently exist to the stagging area
    public void add(String filename) {
        //if the current working version of the file is identical to the version in the current commit do not stage!
        //if the file does not exist at all,print an error message
        if (!join(CWD, filename).exists()) {
            System.out.println("File does not exist.");
            return;
        }
        //if the current working version of the file is identical to the version in the current commit, do not stage it
        if (join(GITLET_DIR, "object", "commit", "HEAD", filename).exists()) {
            if (join(CWD, filename).equals(join(GITLET_DIR, "object", "commit", "HEAD", filename))) {
                return;
            }
        }
        //if the file is not staged, add it to the staging area
        if (!join(GITLET_DIR, "staging", filename).exists()) {
            writeContents(join(GITLET_DIR, "staging", filename), readContentsAsString(join(CWD, filename)));
        }
        //if the file is already staged, overwrite the file in the staging area with the new version
        else {
            writeContents(join(GITLET_DIR, "staging", filename), readContentsAsString(join(CWD, filename)));
        }
    }
  1. 将指定的文件添加到暂存区中

commit函数

//commit the files in the staging area
    public void commit(String message) {
        //if no files have been staged, print an error message
        if (join(GITLET_DIR,"stageing").list().length == 1) {
            System.out.println("No changes added to the commit.");
            return;
        }
        //create a new commit object and set the parent commit
        //TODO: figure out how the blobs work
        Commit newCommit = new Commit(message, readObject(join(GITLET_DIR, "HEAD", "HEAD"), Commit.class), String.valueOf(System.currentTimeMillis()), null);
        //create a new commit file
        File commitFile = join(GITLET_DIR, "object", "commit", newCommit.getUID());
        //serialize the commit object and write it to the commit file
        writeObject(commitFile, newCommit);
        //update the head to the new commit
        writeContents(join(GITLET_DIR, "HEAD", "HEAD"), newCommit.getUID());
        //clear the staging area
        for (File file : join(GITLET_DIR, "staging").listFiles()) {
            file.delete();
        }
    }
  1. 新建一个commit对象记录当前的项目状态。

rm函数

//remove the file from the staging area
    public void rm(String filename) {
        //if the file is not staged, print an error message
        if (!join(GITLET_DIR, "staging", filename).exists()) {
            System.out.println("No reason to remove the file.");
            return;
        }
        //remove the file from the staging area
        join(GITLET_DIR, "staging", filename).delete();
    }
  1. 从暂存区中将已经添加的某个文件删除。

log函数

//print the commit history, but we only display the first parent commit links and ignore any second parent links
    public void log() {
        //get into the commit directory
        File commit = join(GITLET_DIR, "object", "commit");
        //get the current commit and deserialize it to a commit object
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD", "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        //print the commit history
        while (current != null) {
            System.out.println("===");
            System.out.println("commit " + current.getUID());
            System.out.println("Date: " + current.getTimestamp());
            System.out.println(current.getMessage());
            System.out.println();
            current = current.getParent();//implement the circular of the commit messages
        }
    }
  1. 从commit文件夹下获取当前分支的commit信息并打印在控制台上面。

global_log函数

//print the commit history of all commits
    public void global_log() {
        //get the global log of all commits
        File commit = join(GITLET_DIR, "object", "commit");
        for (File file : commit.listFiles()) {
            Commit current = readObject(file, Commit.class);
            System.out.println("===");
            System.out.println("commit " + current.getUID());
            System.out.println("Date: " + current.getTimestamp());
            System.out.println(current.getMessage());
            System.out.println();
        }
    }
  • 在全局范围内打印所有的commit信息。

find函数

//find the commit with the given message
    public void find(String message) {
        //get the global log of all commits
        File commit = join(GITLET_DIR, "object", "commit");
        for (File file : commit.listFiles()) {
            Commit current = readObject(file, Commit.class);
            if (current.getMessage().equals(message)) {
                System.out.println(current.getUID());//print the commit message by line
                return;
            }
        }
    }
  • 根据文件名找到相应的commit message

status函数

//print the status of the repository
    public void status() {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //print the current branch
        System.out.println("=== Branches ===");
        System.out.println("*" + currentBranch);
        for (File file : join(GITLET_DIR, "object", "commit").listFiles()) {
            if (!file.getName().equals(currentBranch)) {
                System.out.println(file.getName());
            }
        }
        System.out.println();
        //print the staged files
        System.out.println("=== Staged Files ===");
        for (File file : join(GITLET_DIR, "staging").listFiles()) {
            System.out.println(file.getName());
        }
        System.out.println();
        //print the removed files
        System.out.println("=== Removed Files ===");
        for (File file : join(GITLET_DIR, "staging").listFiles()) {
            System.out.println(file.getName());
        }
        System.out.println();
        //print the modified files
        System.out.println("=== Modifications Not Staged For Commit ===");
        System.out.println();
        //print the untracked files
        System.out.println("=== Untracked Files ===");
        System.out.println();
    }
  • 打印当前的暂存区的状态

checkout部分综合代码

 //checkout the file from the current commit
    public void checkout(String filename) {
        //get the current commit
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        //get the file from the current commit
        File file = join(GITLET_DIR, "object", "blob", current.getUID(), filename);
        //copy the file to the current working directory
        writeContents(join(CWD, filename), readContents(file));
    }
    //checkout the file from the commit id
    public void checkout(String commitID, String filename) {
        //get the commit from the commit id
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, commitID);
        Commit current = readObject(currentCommit, Commit.class);
        //get the file from the commit
        File file = join(GITLET_DIR, "object", "blob", current.getUID(), filename);
        //copy the file to the current working directory
        writeContents(join(CWD, filename), readContents(file));
    }
    //checkout the branch
    public void checkoutBranch(String branchName) {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //if the branch does not exist, print an error message
        if (!join(GITLET_DIR, "object", "commit", branchName).exists()) {
            System.out.println("No such branch exists.");
            return;
        }
        //if the branch is the current branch, print an error message
        if (currentBranch.equals(branchName)) {
            System.out.println("Already on the target branch, no need to change the branch");
            return;
        }
        //get the current commit
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        //get the branch commit
        File branchCommit = join(commit, branchName);
        Commit branch = readObject(branchCommit, Commit.class);
        //get the files from the branch commit
        for (File file : join(GITLET_DIR, "object", "blob", branch.getUID()).listFiles()) {
            //copy the file to the current working directory
            writeContents(join(CWD, file.getName()), readContents(file));
        }
        //delete the files that are not in the branch commit
        for (File file : join(CWD).listFiles()) {
            if (!join(GITLET_DIR, "object", "blob", branch.getUID(), file.getName()).exists()) {
                file.delete();
            }
        }
        //update the head to the branch commit
        writeContents(join(GITLET_DIR, "HEAD"), branchName);
    }
  • 分支切换以及状态更新

branch函数

//Description: Creates a new branch with the given name, and points it at the current head commit. A branch is nothing more than a name for a reference (a SHA-1 identifier) to a commit node. This command does NOT immediately switch to the newly created branch (just as in real Git). Before you ever call branch, your code should be running with a default branch called “master”.
    public void branch(String branchName) {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //if the branch already exists, print an error message
        if (join(GITLET_DIR, "object", "commit", branchName).exists()) {
            System.out.println("A branch with that name already exists.");
            return;
        }
        //create a new branch commit
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        Commit newBranch = new Commit(current.getMessage(), current, String.valueOf(System.currentTimeMillis()), null);
        //create a new branch commit file
        File branchCommit = join(commit, branchName);
        //serialize the branch commit object and write it to the branch commit file
        writeObject(branchCommit, newBranch);
    }
  • 创建一个新的branch

rm_branch函数

//remove the branch
    public void rm_branch(String branchName) {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //if the branch does not exist, print an error message
        if (!join(GITLET_DIR, "object", "commit", branchName).exists()) {
            System.out.println("A branch with that name does not exist.");
            return;
        }
        //if the branch is the current branch, print an error message
        if (currentBranch.equals(branchName)) {
            System.out.println("Cannot remove the current branch.");
            return;
        }
        //remove the branch
        join(GITLET_DIR, "object", "commit", branchName).delete();
    }
  • 删除一个分支

reset函数

//reset the commit header to the given commit
    public void reset(String commitID) {
        //get the commit from the commit id
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, commitID);
        Commit current = readObject(currentCommit, Commit.class);
        //get the files from the commit
        for (File file : join(GITLET_DIR, "object", "blob", current.getUID()).listFiles()) {
            //copy the file to the current working directory
            writeContents(join(CWD, file.getName()), readContents(file));
        }
        //delete the files that are not in the commit
        for (File file : join(CWD).listFiles()) {
            if (!join(GITLET_DIR, "object", "blob", current.getUID(), file.getName()).exists()) {
                file.delete();
            }
        }
        //update the head to the commit
        writeContents(join(GITLET_DIR, "HEAD"), commitID);
    }

merge函数

//merge the branch with the current branch
    public void merge(String branchName) {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //if the branch does not exist, print an error message
        if (!join(GITLET_DIR, "object", "commit", branchName).exists()) {
            System.out.println("A branch with that name does not exist.");
            return;
        }
        //if the branch is the current branch, print an error message
        if (currentBranch.equals(branchName)) {
            System.out.println("Cannot merge a branch with itself.");
            return;
        }
        //get the current commit
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        //get the branch commit
        File branchCommit = join(commit, branchName);
        Commit branch = readObject(branchCommit, Commit.class);
        //get the split point commit
        Commit splitPoint = findSplitPoint(current, branch);
        //get the files from the split point commit
        for (File file : join(GITLET_DIR, "object", "blob", splitPoint.getUID()).listFiles()) {
            //copy the file to the current working directory
            writeContents(join(CWD, file.getName()), readContents(file));
        }
        //get the files from the branch commit
        for (File file : join(GITLET_DIR, "object", "blob", branch.getUID()).listFiles()) {
            //if the file is not in the split point commit, copy the file to the current working directory
            if (!join(GITLET_DIR, "object", "blob", splitPoint.getUID(), file.getName()).exists()) {
                writeContents(join(CWD, file.getName()), readContents(file));
            }
        }
        //get the files from the current commit
        for (File file : join(GITLET_DIR, "object", "blob", current.getUID()).listFiles()) {
            //if the file is not in the split point commit, copy the file to the current working directory
            if (!join(GITLET_DIR, "object", "blob", splitPoint.getUID(), file.getName()).exists()) {
                writeContents(join(CWD, file.getName()), readContents(file));
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/559899.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Navicat导入sql文件图文教程

本文使用的MySQL工具为:Navicat.默认已经连接数据库!! 步骤: 1.右键自己的数据库,选择新建数据库. 2.输入数据库名称,字符集选择“utf8”,排序规则选择“ utf8_general_ci”,确定. 3.双击新建好的“数据库”。右键点击“运行SQL文件”。 4.选择本地的s…

2024年安装tf tfa tfh

目的: 在win10上,anaconda内,同时安装tensorflow tensorflow_hub tensorflow_addons。需要注意3个版本相互对应。 本文最后找到一种方法:先用pip安装tensorflow2.14版本,再次使用pip安装剩余两个时,就会自…

姑苏寻韵~庆开放原子开源大赛 OpenTiny 前端 Web 应用开发挑战赛路演圆满落幕。

春日已至,姑苏古城迎来了一场编程的盛宴——开放原子开源大赛OpenTiny前端Web应用开发挑战赛。历时三个月的激烈角逐,OpenTiny与众多开发者携手共赴这场智慧的较量。决赛路演于4月14日在苏州(太湖)产业软件园圆满落下帷幕~ 开放原…

圣地亚哥 Toler 小学利用School AI帮助每个学生都有自己的聊天机器人,提高学习兴趣和效率

圣地亚哥 Toler 小学利用 AI 程序 SchoolAI 平台为学生创建个性化的聊天机器人,帮助他们更好地学习和提问。这个 AI 程序让学生可以在几秒钟内得到问题的答案,激发了他们提出更多问题的好奇心。 管理、调节和指导学生如何通过任务控制使用人工智能。 当…

JUC(java.util.concurrent) 的常见类

Callable 接口 Callable 的用法 Callable 是一个 interface(类似之前的 Runnable,用来描述一个任务,但是没有返回值)也是描述一个任务的,有返回值。方便程序猿借助多线程的方式计算结果. 例如:创建线程…

CZT Blusetein‘s FFT

参考文献: [Sto66] Stockham Jr T G. High-speed convolution and correlation[C]//Proceedings of the April 26-28, 1966, Spring joint computer conference. 1966: 229-233.[Blu68] Bluestein L. A linear filtering approach to the computation of discrete …

代码优化实践之税率计算问题

开篇 今天的问题来自于《编程珠玑》第三章【数据决定程序结构】,这里提出了几条代码优化相关的原则,受益不浅。下面是提到的几条原则: 使用数组重新编写重复代码。冗长的相似代码往往可以使用最简单的数据结构——数组来更好的表述&#xff1…

Vue3: toRefs与toRef的基本使用

一、前言 本文主要介绍toRefs与toRef的基本使用。 二、内容 1、基本概念 作用: toRefs与toRef可以将一个响应式对象中的每一 个属性,转换为ref对象;不同 toRefs与toRef功能一致,但toRefs可以批量转换。 2、toRefs 如果把reactive定义的…

ROS仿真小车(四)—— URDF与Gazebo集成

文章目录 前言一、ubuntu20.04中下载gazebo_models二、在gazebo中显示简单模型1 创建功能包,导入依赖2 编写URDF文件3 编写launch文件4 在gazebo中显示机器人模型 三、URDF集成Gazebo相关设置四、在gazebo中导入小车模型1 编写xacro文件2 编写launch文件3 运行结果 …

Stable Diffusion 模型分享:MeinaMix(动漫)meinamix_meinaV11

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 MeinaMix 的目标是:能够在很少的提示下…

SpectralMamba:用于高光谱图像分类的高效 Mamba

SpectralMamba:用于高光谱图像分类的高效 Mamba 摘要IntroductionMethodologyPreliminariesSpectralMamba: OverviewSpectralMamba: Key ComponentsB1 Piece-wise Sequential ScanningIii-B2 Gated Spatial-Spectral Merging SpectralMamba: Efficient Mamba for Hy…

【InternLM 实战营第二期作业06】Lagent AgentLego 智能体应用搭建

基础作业 1.完成 Lagent Web Demo 使用 使用 LMDeploy 部署 conda activate agent lmdeploy serve api_server /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-7b \--server-name 127.0.0.1 \--model-name internlm2-chat-7b \--cache-max-entry-count 0.1 …

Linux文件的特殊权限(SUID|SGID|SBIT)

一、SUID 介绍:SUID是一种对二进制程序进行设置的特殊权限,能够让二进制程序的执行者临时拥有所有者的权限(仅对拥有执行权限的二进制程序有效)。 (一)语法格式 chmod us 文件名(设置SUID权限…

SOLIDWORKS批量改名工具个人版 慧德敏学

每个文件都会有自己的名字,SOLIDWOKRKS模型也不例外。但是如果从资源管理器直接修改模型的文件名,就会导致模型关联的丢失,导致装配体打开之后找不到模型,因此就需要使用SOLIDWORKS的重命名功能。 SOLIDWORKS批量改名插件- Solid…

智能电网线路阻抗模拟器基础认识

智能电网线路阻抗模拟器是专门用于模拟电力系统输电线路阻抗特性的装置,它能够根据设定的参数,精确地模拟出各种不同类型、不同长度和不同截面积的输电线路在正常运行或故障状态下的阻抗特性。这种模拟器在电力系统的规划、设计、运行和维护中起着重要的…

交换机的种类有哪些?主要都具有哪些作用?

在当今数字化时代,网络已经成为我们生活和工作中不可或缺的一部分。无论是家庭网络还是企业网络,都需要有效的网络设备来实现数据通信和资源共享。而网络交换机作为一种重要的网络设备,扮演着连接和管理网络设备的关键角色。本文将探讨交换机…

TXT文本编辑器,高效将文本里特定符号前的内容作为关键词一键复制或移动文件,效管理文件内容

在日常工作和生活中,我们经常需要处理大量的文件,而文件的管理和整理则成为了一个重要的问题。传统的文件管理方式不仅效率低下,而且容易出错。为了解决这一难题,我们推出了一款强大的TXT文本编辑器,它能够帮助你以文件…

岩石变角剪切试验夹具 技术参数

岩石变角试验夹具是根据TB10115-2014铁路工程岩石试验规程等标准利用压力机施加垂直荷载,通过一套特制的夹具使试件沿某一剪切面产生剪切破坏,然后通过静力平衡条件解析剪切面上的法向压应力和剪应力,从而绘制法向压应力(σ)与剪应力(τ&…

flutter release 报错 Error: SocketException: Failed host lookup:

flutter 的 debug 模式没有任何问题 ,打了release 包后一直报下面的错,查了一下是 因为没有网络权限 Error: SocketException: Failed host lookup: yomi-test-aws-sg.yomigame.games (OS Error: No address associated with hostname, errno 7) 按照下…

YOLOv5 / YOLOv7 / YOLOv8 / YOLOv9 / RTDETR -gui界面-交互式图形化界面

往期热门博客项目回顾:点击前往 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 AI健身教练-引体向上…