使用服务器端git hook来阻止CSS(从SASS编译)被推送,但允许推送其他CSS文件

时间:2016-11-19 12:24:45

标签: git bash githooks

我们正在转换一个项目,用SASS替换一些CSS文件。

在使用.scss文件进行开发期间,.css文件会自动生成,但我们不希望在存储库中提交这些文件。

假设我们有一个名为loginModule的模块,它位于文件夹login中。在login内,我们目前有两个CSS文件:login.cssux-theme.css。我想将login.css替换为login.scss。在推送我的代码时,如果login.css存在,我将无法推送login.scss

确保同一目录中不存在具有相同名称的.scss.css文件的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

您已经具体询问了服务器端挂钩,即预接收或更新挂钩,但当然,此处至少有两个方面:服务器和客户端。在客户端上,作业是或者至少可以更容易,因为您可以处理普通文件系统中的普通文件。 (目前只有)其他answer by 0.sh执行此类操作,但不是作为挂钩,甚至不使用任何实际的Git命令:它只添加.gitignore条目,如果已​​经跟踪了文件,无论如何,这些参赛作品都没有用。

我将解决您提出的服务器端问题,因为服务器是唯一的位置,您可以强制执行完全禁止。问题是预接收和更新挂钩难以编写

无论你选择哪种钩子,都要记住在命令行中使用参数或stdin上的一系列输入行调用,为你提供 ref-name (对于{{1一个引用,作为参数)或完整的引用集(update:所有refs,作为输入流)要更新。您的工作是验证您是否同意建议的更新,如果是,则退出为零状态,否则退出非零状态。

我在this sample that checks for merge commits的预接收挂钩中说明了这样做的机制。在您的情况下,您可能会执行类似的操作,但替换函数pre-receive,以便检查添加的提交而不是检查合并。 内容。还要记住修改check_branch_add_commits以处理"删除一些提交,添加其他提交"案件也在这里。当一些提交被删除时,它们在check_branch_update的输出中;当添加一些提交时,它们位于git rev-list $NEW..$OLD的输出中。 (由于git rev-list $OLD..$NEW检查了这些,你可以简单地在所有情况下调用它。)

接下来,为了检查添加的提交,您必须逐个遍历它们:

check_branch_add_commits

其中local rev for rev in $(git rev-list $OLD..$NEW); do check_one_commit $rev done 检查指定的提交。

您的测试归结为"如果名称 .scss存在,则禁止现有" 名称 .css在某些(所有?)目录集中,因此check_one_rev_commit必须检查指定的提交(check_one_commit将是其哈希)。这个命令:

$1

生成提交中每个文件的列表。只列出带有嵌入空格的文件名,但如果文件名具有嵌入的换行符,则会对其进行编码:

git ls-tree -r --name-only $1

您可能希望以不同方式处理此问题,或在编写程序以阅读名称时使用$ git ls-tree -r --name-only HEAD foo has * star "has a \nnewline" name with a space 选项。

接下来,您必须编写一个程序来读取名称。 : - )

这个程序会相当复杂。你确实得到了一个很好的保证:每个子目录中的所有名称都将是" clustered"进入该目录,例如,这是来自真实存储库的部分-z

git ls-tree -r --name-only

这里的两个子目录是rfuncs.c rfuncs.h sbuf/sbuf.c sbuf/sbuf.h transport/socket.c transport/socket.h utils.c sbuf,正如您所看到的,它们列在所有" r" -named文件之后和任何&#34之前; u" - 已命名的文件,按排序顺序。

然后,如果没有包含任何transport文件且包含相应*.scss的目录,那么您的程序任务将从stdin读取文件列表并退出0(成功)文件,如果有,则为非零。 (如果使用*.css,则可以读取每个ASCII NUL字符。)然后,您可以执行此操作:

-z

您的检查程序可能会打印 提交错误的原因(即scss和css文件的完整路径名冲突)。

编写这个程序还有一件小事,但我把它留给你。如果您的程序读取标准输入,则很容易测试:只需准备一份"建议的if git ls-tree -r --name-only -z $rev | /path/to/program/to/check; then # do nothing, this commit is OK else echo "bad commit found at $rev" STATUS=1 # assuming my general framework fi 输出列表"并在每一个上运行它,确保它拒绝该树或接受它,这取决于该树是否符合您的特定标准。

答案 1 :(得分:0)

如果我非常理解您的问题,如果login.scss存在于login.css所在的同一目录中,则您不想推login.scss。你必须编写这个脚本。也许这就是你想要的我不知道的。

#!/bin/bash
checkIfFileMatch() {
   file=${1}
  if [[ ! -f $file ]];then
    echo "$file not found in $(pwd)"
    return 2
  fi
   filename=${file%.*}
  for i in *;do
    remExt=${i%.*}       
    if [[ $remExt != $filename ]];then
            printf "%s\n" "$i" >> .gitignore
    fi
  done
}

 checkIfFileMatch "login.scss"

您必须将单个文件传递给checkIfFileMatch

脚本的作用是,它需要一个争论并检查文件是否存在于当前工作目录中,然后删除文件扩展名。在for循环*中列出了当前工作目录中的所有文件。 if语句检查传递给checkIfFileMatch的文件名是否等于循环中的任何文件。运行此脚本,其中包含scss文件。在>> .gitignore所在的位置,将其替换为您git init所在的目录>> /root/MyProject/App/.gitignore