🎨 同步忽略文件配置使用 gitignore 规则 https://github.com/siyuan-note/siyuan/issues/5295
This commit is contained in:
parent
4c81634ab7
commit
070f51a3ab
6 changed files with 18 additions and 227 deletions
|
@ -282,12 +282,12 @@ SiYuan is made possible by the following open source projects.
|
|||
* [https://github.com/imroc/req](https://github.com/imroc/req) `MIT License`
|
||||
* [https://github.com/jinzhu/copier](https://github.com/jinzhu/copier) `MIT License`
|
||||
* [https://github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) `MIT License`
|
||||
* [https://github.com/mattn/go-zglob](https://github.com/mattn/go-zglob) `MIT License`
|
||||
* [https://github.com/mitchellh/go-ps](https://github.com/mitchellh/go-ps) `MIT License`
|
||||
* [https://github.com/mssola/user_agent](https://github.com/mssola/user_agent) `MIT License`
|
||||
* [https://github.com/panjf2000/ants](https://github.com/panjf2000/ants) `MIT License`
|
||||
* [https://github.com/patrickmn/go-cache](https://github.com/patrickmn/go-cache) `MIT License`
|
||||
* [https://github.com/radovskyb/watcher](https://github.com/radovskyb/watcher) `BSD-3-Clause License`
|
||||
* [https://github.com/sabhiram/go-gitignore](https://github.com/sabhiram/go-gitignore) `MIT License`
|
||||
* [https://github.com/siyuan-note/dejavu](https://github.com/siyuan-note/dejavu) `Mulan PSL v2`
|
||||
* [https://github.com/siyuan-note/encryption](https://github.com/siyuan-note/encryption) `Mulan PSL v2`
|
||||
* [https://github.com/siyuan-note/filelock](https://github.com/siyuan-note/filelock) `Mulan PSL v2`
|
||||
|
|
|
@ -291,12 +291,12 @@
|
|||
* [https://github.com/imroc/req](https://github.com/imroc/req) `MIT License`
|
||||
* [https://github.com/jinzhu/copier](https://github.com/jinzhu/copier) `MIT License`
|
||||
* [https://github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) `MIT License`
|
||||
* [https://github.com/mattn/go-zglob](https://github.com/mattn/go-zglob) `MIT License`
|
||||
* [https://github.com/mitchellh/go-ps](https://github.com/mitchellh/go-ps) `MIT License`
|
||||
* [https://github.com/mssola/user_agent](https://github.com/mssola/user_agent) `MIT License`
|
||||
* [https://github.com/panjf2000/ants](https://github.com/panjf2000/ants) `MIT License`
|
||||
* [https://github.com/patrickmn/go-cache](https://github.com/patrickmn/go-cache) `MIT License`
|
||||
* [https://github.com/radovskyb/watcher](https://github.com/radovskyb/watcher) `BSD-3-Clause License`
|
||||
* [https://github.com/sabhiram/go-gitignore](https://github.com/sabhiram/go-gitignore) `MIT License`
|
||||
* [https://github.com/siyuan-note/dejavu](https://github.com/siyuan-note/dejavu) `Mulan PSL v2`
|
||||
* [https://github.com/siyuan-note/encryption](https://github.com/siyuan-note/encryption) `Mulan PSL v2`
|
||||
* [https://github.com/siyuan-note/filelock](https://github.com/siyuan-note/filelock) `Mulan PSL v2`
|
||||
|
|
|
@ -33,13 +33,13 @@ require (
|
|||
github.com/imroc/req/v3 v3.13.1
|
||||
github.com/jinzhu/copier v0.3.5
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
github.com/mattn/go-zglob v0.0.3
|
||||
github.com/mitchellh/go-ps v1.0.0
|
||||
github.com/mssola/user_agent v0.5.3
|
||||
github.com/panjf2000/ants/v2 v2.5.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/qiniu/go-sdk/v7 v7.13.0
|
||||
github.com/radovskyb/watcher v1.0.7
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
|
||||
github.com/siyuan-note/dejavu v0.0.0-20220626025117-e5db5c782cbb
|
||||
github.com/siyuan-note/encryption v0.0.0-20220612074546-f1dd94fe8676
|
||||
github.com/siyuan-note/eventbus v0.0.0-20220624162334-ca7c06dc771f
|
||||
|
@ -93,7 +93,6 @@ require (
|
|||
github.com/pelletier/go-toml/v2 v2.0.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/restic/chunker v0.4.0 // indirect
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||
|
|
|
@ -345,8 +345,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
|||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-zglob v0.0.3 h1:6Ry4EYsScDyt5di4OI6xw1bYhOqfE5S33Z1OPy+d+To=
|
||||
github.com/mattn/go-zglob v0.0.3/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
|
@ -423,8 +421,6 @@ github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJ
|
|||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20220626024131-25831e573009 h1:w2GvjKF1xFn+Swo+e+eOL9l/KQ8FvtJbwshsBInuPKg=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20220626024131-25831e573009/go.mod h1:i7dnOgHM41EA7xIX2CYSxYe0WhksGZidQQsLvWryK7w=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20220626025117-e5db5c782cbb h1:7HmFGziI6a8JctJ9ouuZ4fHSsFH1GXhGfoN5pxIc2Ds=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20220626025117-e5db5c782cbb/go.mod h1:i7dnOgHM41EA7xIX2CYSxYe0WhksGZidQQsLvWryK7w=
|
||||
github.com/siyuan-note/encryption v0.0.0-20220612074546-f1dd94fe8676 h1:QB9TjJQFhXhZ6dAtPpY02DlzHAQm1C+WqZq6OadG8mI=
|
||||
|
|
|
@ -38,7 +38,6 @@ import (
|
|||
"github.com/88250/lute/html"
|
||||
"github.com/88250/lute/parse"
|
||||
"github.com/88250/protyle"
|
||||
"github.com/mattn/go-zglob"
|
||||
"github.com/siyuan-note/filelock"
|
||||
"github.com/siyuan-note/siyuan/kernel/filesys"
|
||||
"github.com/siyuan-note/siyuan/kernel/sql"
|
||||
|
@ -234,21 +233,22 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
assetsDirs, err := zglob.Glob(unzipRootPath + "/**/assets")
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
if 0 < len(assetsDirs) {
|
||||
for _, assets := range assetsDirs {
|
||||
if gulu.File.IsDir(assets) {
|
||||
dataAssets := filepath.Join(util.DataDir, "assets")
|
||||
if err = gulu.File.Copy(assets, dataAssets); nil != err {
|
||||
util.LogErrorf("copy assets from [%s] to [%s] failed: %s", assets, dataAssets, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
os.RemoveAll(assets)
|
||||
var assetsDirs []string
|
||||
filepath.Walk(unzipRootPath, func(path string, info fs.FileInfo, err error) error {
|
||||
if strings.Contains(path, "assets") && info.IsDir() {
|
||||
assetsDirs = append(assetsDirs, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
for _, assets := range assetsDirs {
|
||||
if gulu.File.IsDir(assets) {
|
||||
dataAssets := filepath.Join(util.DataDir, "assets")
|
||||
if err = gulu.File.Copy(assets, dataAssets); nil != err {
|
||||
util.LogErrorf("copy assets from [%s] to [%s] failed: %s", assets, dataAssets, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
os.RemoveAll(assets)
|
||||
}
|
||||
|
||||
writingDataLock.Lock()
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
// SiYuan - Build Your Eternal Digital Garden
|
||||
// Copyright (c) 2020-present, b3log.org
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package util
|
||||
|
||||
// 该文件代码来自 https://github.com/go-git/go-git 项目,Apache-2.0 license
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// https://github.com/go-git/go-git/blob/master/plumbing/format/gitignore/matcher.go
|
||||
|
||||
// Matcher defines a global multi-pattern matcher for gitignore patterns
|
||||
type Matcher interface {
|
||||
// Match matches patterns in the order of priorities. As soon as an inclusion or
|
||||
// exclusion is found, not further matching is performed.
|
||||
Match(path []string, isDir bool) bool
|
||||
}
|
||||
|
||||
// NewMatcher constructs a new global matcher. Patterns must be given in the order of
|
||||
// increasing priority. That is most generic settings files first, then the content of
|
||||
// the repo .gitignore, then content of .gitignore down the path or the repo and then
|
||||
// the content command line arguments.
|
||||
func NewMatcher(ps []Pattern) Matcher {
|
||||
return &matcher{ps}
|
||||
}
|
||||
|
||||
type matcher struct {
|
||||
patterns []Pattern
|
||||
}
|
||||
|
||||
func (m *matcher) Match(path []string, isDir bool) bool {
|
||||
n := len(m.patterns)
|
||||
for i := n - 1; i >= 0; i-- {
|
||||
if match := m.patterns[i].Match(path, isDir); match > NoMatch {
|
||||
return match == Exclude
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// https://github.com/go-git/go-git/blob/master/plumbing/format/gitignore/pattern.go
|
||||
|
||||
// MatchResult defines outcomes of a match, no match, exclusion or inclusion.
|
||||
type MatchResult int
|
||||
|
||||
const (
|
||||
// NoMatch defines the no match outcome of a match check
|
||||
NoMatch MatchResult = iota
|
||||
// Exclude defines an exclusion of a file as a result of a match check
|
||||
Exclude
|
||||
// Include defines an explicit inclusion of a file as a result of a match check
|
||||
Include
|
||||
)
|
||||
|
||||
const (
|
||||
inclusionPrefix = "!"
|
||||
zeroToManyDirs = "**"
|
||||
patternDirSep = "/"
|
||||
)
|
||||
|
||||
// Pattern defines a single gitignore pattern.
|
||||
type Pattern interface {
|
||||
// Match matches the given path to the pattern.
|
||||
Match(path []string, isDir bool) MatchResult
|
||||
}
|
||||
|
||||
type pattern struct {
|
||||
domain []string
|
||||
pattern []string
|
||||
inclusion bool
|
||||
dirOnly bool
|
||||
isGlob bool
|
||||
}
|
||||
|
||||
// ParsePattern parses a gitignore pattern string into the Pattern structure.
|
||||
func ParsePattern(p string, domain []string) Pattern {
|
||||
res := pattern{domain: domain}
|
||||
|
||||
if strings.HasPrefix(p, inclusionPrefix) {
|
||||
res.inclusion = true
|
||||
p = p[1:]
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(p, "\\ ") {
|
||||
p = strings.TrimRight(p, " ")
|
||||
}
|
||||
|
||||
if strings.HasSuffix(p, patternDirSep) {
|
||||
res.dirOnly = true
|
||||
p = p[:len(p)-1]
|
||||
}
|
||||
|
||||
if strings.Contains(p, patternDirSep) {
|
||||
res.isGlob = true
|
||||
}
|
||||
|
||||
res.pattern = strings.Split(p, patternDirSep)
|
||||
return &res
|
||||
}
|
||||
|
||||
func (p *pattern) Match(path []string, isDir bool) MatchResult {
|
||||
if len(path) <= len(p.domain) {
|
||||
return NoMatch
|
||||
}
|
||||
for i, e := range p.domain {
|
||||
if path[i] != e {
|
||||
return NoMatch
|
||||
}
|
||||
}
|
||||
|
||||
path = path[len(p.domain):]
|
||||
if p.isGlob && !p.globMatch(path, isDir) {
|
||||
return NoMatch
|
||||
} else if !p.isGlob && !p.simpleNameMatch(path, isDir) {
|
||||
return NoMatch
|
||||
}
|
||||
|
||||
if p.inclusion {
|
||||
return Include
|
||||
} else {
|
||||
return Exclude
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pattern) simpleNameMatch(path []string, isDir bool) bool {
|
||||
for i, name := range path {
|
||||
if match, err := filepath.Match(p.pattern[0], name); err != nil {
|
||||
return false
|
||||
} else if !match {
|
||||
continue
|
||||
}
|
||||
if p.dirOnly && !isDir && i == len(path)-1 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *pattern) globMatch(path []string, isDir bool) bool {
|
||||
matched := false
|
||||
canTraverse := false
|
||||
for i, pattern := range p.pattern {
|
||||
if pattern == "" {
|
||||
canTraverse = false
|
||||
continue
|
||||
}
|
||||
if pattern == zeroToManyDirs {
|
||||
if i == len(p.pattern)-1 {
|
||||
break
|
||||
}
|
||||
canTraverse = true
|
||||
continue
|
||||
}
|
||||
if strings.Contains(pattern, zeroToManyDirs) {
|
||||
return false
|
||||
}
|
||||
if len(path) == 0 {
|
||||
return false
|
||||
}
|
||||
if canTraverse {
|
||||
canTraverse = false
|
||||
for len(path) > 0 {
|
||||
e := path[0]
|
||||
path = path[1:]
|
||||
if match, err := filepath.Match(pattern, e); err != nil {
|
||||
return false
|
||||
} else if match {
|
||||
matched = true
|
||||
break
|
||||
} else if len(path) == 0 {
|
||||
// if nothing left then fail
|
||||
matched = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if match, err := filepath.Match(pattern, path[0]); err != nil || !match {
|
||||
return false
|
||||
}
|
||||
matched = true
|
||||
path = path[1:]
|
||||
}
|
||||
}
|
||||
if matched && p.dirOnly && !isDir && len(path) == 0 {
|
||||
matched = false
|
||||
}
|
||||
return matched
|
||||
}
|
Loading…
Add table
Reference in a new issue