IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> libgit2 returned: path too long: -> 正文阅读

[开发工具]libgit2 returned: path too long:

前言

在进行工作的git总提交, git客户端使用TortoiseGit
先将前一段时间(应该有半年以上都是在本地开发), 离线开发的内容push到git服务器, 这个对, 没有问题.

还有一部分在公司svn服务器目录迁出的工程, 有修改, svn服务器打开后, 这部分提交也没有问题.

想起自己本本上还有很多本地svn归档的开发成果, 这个也想提交到git日志.
如果能提交成功, 以后同事就可以迁出我的git目录, 自己去找. 公司有一份底子.

直接将本地svn目录拷贝到git迁出目录, 将.svn目录都去掉.
然后进行 git add, 然后出现报错如下:

libgit2 returned: path too long:

这个报错是目录或文件的全路径名称太长了.
这个长度限制是MAX_PATH, 不能大于260个字节.

简单测试如下, 可以看出全路径名称的限制就是260.

void test(void)
{
	// libgit2 returned: path too long: 'D:/my_dev/xxxx_git_checkout/xxxx_rep_xxxxxxxx/local_svn_bk/rzxxxx_local/src/prj/bottom_board/doc/stm32cube_fw_f0_v1112/STM32Cube_FW_F0_V1.11.0/Projects/STM32072B_EVAL/Applications/FreeRTOS/FreeRTOS_SemaphoreFromISR/SW4STM32/STM32072B_EVAL/STM32F072VBTx_FLASH.ld'
	const char* psz_path_name = "D:/my_dev/xxxx_git_checkout/xxxx_rep_xxxxxxxx/local_svn_bk/rz3609_local/src/prj/bottom_board/doc/stm32cube_fw_f0_v1112/STM32Cube_FW_F0_V1.11.0/Projects/STM32072B_EVAL/Applications/FreeRTOS/FreeRTOS_SemaphoreFromISR/SW4STM32/STM32072B_EVAL/STM32F072VBTx_FLASH.ld";
	int cb_len = (int)strlen(psz_path_name);
	printf("libgit2 returned: path too long: len = %d\n", cb_len);

	// len = 261
	// 说明 TortoiseGit 能操作的全路径文件名最大是260个bytes

	// #define MAX_PATH          260
	printf("MAX_PATH = %d\n", MAX_PATH); // 打印出来的 MAX_PATH也是260
	cb_len = cb_len; // for debug only
}

如果目录中有很多超过MAX_PATH(260)的文件, 等TortoiseGit add 报错了, 再去处理(可以压缩一下顶层目录到.7z, .zip文件), 就可以解决add报错的这个文件.

但是git add 之后, 报错只针对这1个文件, 不会将到底有多少个超出MAX_PATH的文件列出来. git add的时间很长(因为本地svn目录很大), 这要是一个一个报错的处理, 没有这么多时间, 效率太低了.

昨天下班前, 等git add 报错一个文件, 我就处理一个文件. 连续处理了3个文件, 感觉这种方法搞不定了. 得想新方法.

今天上班, 换一种思路.
先自己写个程序, 将放到git目录中的去掉.svn的总本地提交目录中的所有超出MAX_PATH的文件都列出来, 一次性处理掉. 然后在用自己程序再检查一遍, 如果没有漏掉的超长文件, 然后再用git add 就能一次成功. 试了一下, 这招好使.

测试程序

230行的小测试工程, VS2017 console

// find_file_task.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <tchar.h>

bool cb_proc_find_file_who_path_name_len_greate_than_MAX_PATH(const char* psz_dir, const char* psz_file_name);
typedef bool(*PFN_CB_PROC_FIND_FILE)(const char* psz_dir, const char* psz_file_name);

bool find_file_proc(PFN_CB_PROC_FIND_FILE pfn, const char* psz_dir);
__int64 get_file_size(const char* psz_file);

void test(void)
{
	// libgit2 returned: path too long: 'D:/my_dev/xxxx_git_checkout/xxxx_rep_xxxxxxxx/local_svn_bk/rzxxxx_local/src/prj/bottom_board/doc/stm32cube_fw_f0_v1112/STM32Cube_FW_F0_V1.11.0/Projects/STM32072B_EVAL/Applications/FreeRTOS/FreeRTOS_SemaphoreFromISR/SW4STM32/STM32072B_EVAL/STM32F072VBTx_FLASH.ld'
	const char* psz_path_name = "D:/my_dev/xxxx_git_checkout/xxxx_rep_xxxxxxxx/local_svn_bk/rz3609_local/src/prj/bottom_board/doc/stm32cube_fw_f0_v1112/STM32Cube_FW_F0_V1.11.0/Projects/STM32072B_EVAL/Applications/FreeRTOS/FreeRTOS_SemaphoreFromISR/SW4STM32/STM32072B_EVAL/STM32F072VBTx_FLASH.ld";
	int cb_len = (int)strlen(psz_path_name);
	printf("libgit2 returned: path too long: len = %d\n", cb_len);

	// len = 261
	// 说明 TortoiseGit 能操作的全路径文件名最大是260个bytes

	// #define MAX_PATH          260
	printf("MAX_PATH = %d\n", MAX_PATH); // 打印出来的 MAX_PATH也是260
	cb_len = cb_len; // for debug only
}

int main(int argc, char** argv)
{
	const char* psz_dir = NULL;
	bool b_find = false;

	// printf("please attach exe to debug\n");
	// system("pause"); // debug

	do {
		setlocale(LC_ALL, ".936"); ///< 设置中文代码页, 用来显示中文字符
		printf("中文输出测试\n");

		// 通过cmd脚本传进来的中文路径参数乱码, 导致查找文件无效
		// 这和脚本的编码设置有关系
		// 用EditPlus将脚本打开,另存为ansi格式,再运行脚本,传进来的参数(中文路径)就正常了。

		// 如果传进来的要找的文件路径带空格,会导致argc错误, 所以还是将要找的文件拷贝到一个没有空格的路径,然后改一个没有空格的文件名

		// test();

		if (argc < 2)
		{
			printf("usage : THE_EXE dir_path_name\n");
			printf("e.g.    THE_EXE d:\\my_dev_dir\n");
			break;
		}

		psz_dir = argv[1];
		printf("base dir = [%s]\n", psz_dir);

		b_find = find_file_proc(cb_proc_find_file_who_path_name_len_greate_than_MAX_PATH, psz_dir);
		printf("file find %s\n", b_find ? "ok" : "nothing");

	} while (0);

	return EXIT_SUCCESS;
}

bool find_file_proc(PFN_CB_PROC_FIND_FILE pfn, const char* psz_dir)
{
	bool b_rc = false;
	HANDLE hFind = INVALID_HANDLE_VALUE;
	char szDir[MAX_PATH * 4] = {'\0'};
	char szDir_sub[MAX_PATH * 4] = { '\0' };
	WIN32_FIND_DATAA ffd;
	const char* psz_postfix = "\\*.*";
	const char* psz_find_temp = NULL;

	do {
		// https://docs.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory
		memset(szDir, 0, sizeof(szDir));
		strncpy(
			szDir, 
			psz_dir,
			min((sizeof(szDir) - 1), strlen(psz_dir))
		);

		// 如果只遍历给定的目录字符串,只能找到一个文件
		// 要在目录字符串上, 附加"\\*.*"才行
		strncat(
			szDir,
			"\\",
			min(sizeof(szDir) - 1 - strlen(szDir), strlen("\\"))
		);

		strncat(
			szDir,
			"*.*",
			min (sizeof(szDir) - 1 - strlen(szDir), strlen("*.*"))
		);

		// printf("find_file_proc : [%s]\n", szDir);
		hFind = FindFirstFileA(szDir, &ffd);
		if (INVALID_HANDLE_VALUE == hFind)
		{
			printf("error : FindFirstFileA [%s]\n", szDir);
			break;
		}

		do
		{
			if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				// 遍历子目录
				if ((0 != strcmp(".", ffd.cFileName)) && (0 != strcmp("..", ffd.cFileName)) ) {
					// 不遍历的子目录 : 
					// . 
					// .. 

					// 拷贝当前目录到副本
					memset(szDir_sub, 0, sizeof(szDir_sub));
					strncpy(
						szDir_sub,
						psz_dir,
						min((sizeof(szDir_sub) - 1), strlen(psz_dir))
					);

					strncat(
						szDir_sub,
						"\\",
						min(sizeof(szDir_sub) - 1 - strlen(szDir_sub), strlen("\\"))
					);

					// 在当前目录副本上附加子目录
					strncat(
						szDir_sub,
						ffd.cFileName,
						min(sizeof(szDir_sub) - 1 - strlen(szDir_sub), strlen(ffd.cFileName))
					);

					b_rc = find_file_proc(pfn, szDir_sub);
					if (b_rc) {
						break;
					}
				}
			} else {
					// 处理找到的文件
					if (!pfn(psz_dir, ffd.cFileName)) {
						b_rc = true;
						break; // 任务结束, 回调函数说不用再进行文件查找了
					}
			}
		} while (FindNextFileA(hFind, &ffd) != 0);
	} while (0);

	if (INVALID_HANDLE_VALUE != hFind) {
		FindClose(hFind);
		hFind = INVALID_HANDLE_VALUE;
	}

	return b_rc;
}

bool cb_proc_find_file_who_path_name_len_greate_than_MAX_PATH(const char* psz_dir, const char* psz_file_name)
{
	bool b_continue_process = true;
	char sz_buf[MAX_PATH * 4] = { '\0' };
	int len = 0;

	do {
		if ((NULL == psz_dir) || (NULL == psz_file_name)) {
			break;
		}

		memset(sz_buf, 0, sizeof(sz_buf));
		strncpy(sz_buf, psz_dir, min((sizeof(sz_buf) - 1), (strlen(psz_dir))));

		strncat(sz_buf, "\\", min((sizeof(sz_buf) - 1 - strlen(sz_buf)), (strlen("\\"))));
		strncat(sz_buf, psz_file_name, min((sizeof(sz_buf) - 1 - strlen(sz_buf)), (strlen(psz_file_name))));

		len = (int)strlen(sz_buf);
		if (len > MAX_PATH)
		{
			printf("error : len[%d] : [%s]\n", len, sz_buf);
		}
		

		b_continue_process = true;
	} while (0);

	return b_continue_process;
}

__int64 get_file_size(const char* psz_file)
{
	__int64 file_size = -1;
	FILE* pfile = NULL;
	int i_rc = 0;

	do {
		if (NULL == psz_file) {
			break;
		}

		pfile = fopen(psz_file, "rb");
		if (NULL == pfile) {
			break;
		}

		i_rc = _fseeki64(pfile, 0, SEEK_END);
		if (0 != i_rc) {
			break;
		}

		file_size = _ftelli64(pfile);

	} while (0);

	if (NULL != pfile) {
		fclose(pfile);
		pfile = NULL;
	}

	return file_size;
}



用法

在编译好的THE EXE目录, 写一个cmd, 将找到的超长文件都写到一个txt中.
然后对照这个txt, 处理所有超长的文件或目录.

@echo off
rem find_file_task.cmd

cd /d %~dp0
call find_file_task.exe "D:\my_dev\xxxx_git_checkout\xxxx_rep_xxxx\local_svn_bk"  > .\find_result.txt
pause

查找到的超长文件结果文件

在这里插入图片描述
结果文件的样例

中文输出测试
base dir = [D:\my_dev\xxxx_git_checkout\xxxx_rep_xxxxxxxx\local_svn_bk]
error : len[261] : [D:\my_dev\xxxx_git_checkout\xxxx_rep_xxxxxxxx\local_svn_bk\xxxxxx_local\src\prj\bottom_board\doc\stm32cube_fw_f0_v1112\STM32Cube_FW_F0_V1.11.0\Projects\STM32072B_EVAL\Applications\FreeRTOS\FreeRTOS_SemaphoreFromISR\SW4STM32\STM32072B_EVAL\STM32F072VBTx_FLASH.ld]
error : len[263] : [D:\my_dev\xxxx_git_checkout\xxxx_rep_xxxxxxxx\local_svn_bk\xxxxxx_local\src\prj\bottom_board\doc\stm32cube_fw_f0_v1112\STM32Cube_FW_F0_V1.11.0\Projects\STM32072B_EVAL\Applications\TouchSensing\TouchSensing_2touchkeys\SW4STM32\STM32072B_EVAL\STM32F072VBTx_FLASH.ld]
error : len[262] : [D:\my_dev\xxxx_git_checkout\xxxx_rep_xxxxxxxx\local_svn_bk\xxxxxx_local\src\prj\bottom_board\doc\stm32cube_fw_f0_v1112\STM32Cube_FW_F0_V1.11.0\Projects\STM32072B_EVAL\Applications\USB_Device\CustomHID_Standalone\SW4STM32\STM32072B_EVAL_USB\STM32F072VBTx_FLASH.ld]
file find nothing

看找到的len记录, 最长的居然有300, 真惊讶.
剩下的事情, 就是按照查找结果文件, 将要提交的全路径名称都处理到260个字节一下就ok.

总结

刚来公司时, 发现以前同事都在用svn, 我也就用svn, 去现场不方便时, 或者在公司懒得开公司svn服务器时, 就在本地做了一个svn目录.

这样导致很多正式的工作内容都在本地svn目录中, 这样有可能以后总提交时, 很多正式工作成果会由于人工遗漏, 提交不到公司svn服务器.

经常到现场开发的同学, 应该对svn不方便离线开发的场景很厌恶.

后来, 用gogs搭建了git服务器.

用了git之后, 就全身心放松了. 只需要第一次git迁出时, 连接git服务器, 以后离线开发随便弄. 开发完, 直接commit到本地, 一年半年不提交到git服务器都行. 等想起来, 再一次push到公司git服务器. 如果此git目录是多个人公用, 需要先update一下, 有冲突解决冲突, 然后push. 如果此git目录就自己在用, 可以push时, 加上force选项, 一次push了事.

git也有权限控制(挂钩子), 如果简单的用, 可以将给每个同事建立他自己的git仓库, 用账号将库隔开. 如果有参考工程要给他, 可以直接拷贝出来给他.而不是将自己的git库账号给他.

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:50:46  更:2022-02-26 11:52:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:32:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码