github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/actions/lua/path/path.go (about)

     1  package path
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/Shopify/go-lua"
     7  	"github.com/treeverse/lakefs/pkg/actions/lua/util"
     8  )
     9  
    10  const (
    11  	SEPARATOR    = "/"
    12  	HiddenPrefix = "_"
    13  )
    14  
    15  func Open(l *lua.State) {
    16  	open := func(l *lua.State) int {
    17  		lua.NewLibrary(l, library)
    18  		return 1
    19  	}
    20  	lua.Require(l, "path", open, false)
    21  	l.Pop(1)
    22  }
    23  
    24  var library = []lua.RegistryFunction{
    25  	{Name: "parse", Function: parse},
    26  	{Name: "join", Function: join},
    27  	{Name: "is_hidden", Function: isHidden},
    28  	{Name: "default_separator", Function: getDefaultSeparator},
    29  }
    30  
    31  func getDefaultSeparator(l *lua.State) int {
    32  	l.PushString(SEPARATOR)
    33  	return 1
    34  }
    35  
    36  func parse(l *lua.State) int {
    37  	p := lua.CheckString(l, 1)
    38  	sep := SEPARATOR
    39  	if !l.IsNone(2) {
    40  		sep = lua.CheckString(l, 2)
    41  	}
    42  	return util.DeepPush(l, Parse(p, sep))
    43  }
    44  
    45  func getVarArgs(l *lua.State, from int) (vargs []string) {
    46  	for i := from; i <= l.Top(); i++ {
    47  		s, ok := l.ToString(i)
    48  		if !ok {
    49  			lua.Errorf(l, "invalid type, string expected")
    50  			panic("unreachable")
    51  		}
    52  		vargs = append(vargs, s)
    53  	}
    54  	return
    55  }
    56  
    57  func Parse(pth, sep string) map[string]string {
    58  	if strings.HasSuffix(pth, sep) {
    59  		pth = pth[0 : len(pth)-1]
    60  	}
    61  	lastIndex := strings.LastIndex(pth, sep)
    62  	if lastIndex == -1 {
    63  		// no separator
    64  		return map[string]string{
    65  			"parent":    "", // no parent
    66  			"base_name": pth,
    67  		}
    68  	}
    69  	parent := pth[0 : lastIndex+1] // include sep
    70  	baseName := pth[lastIndex+1:]  // don't include sep
    71  	return map[string]string{
    72  		"parent":    parent,
    73  		"base_name": baseName,
    74  	}
    75  }
    76  
    77  func join(l *lua.State) int {
    78  	sep := lua.CheckString(l, 1)
    79  	parts := getVarArgs(l, 2)
    80  	l.PushString(Join(sep, parts...))
    81  	return 1
    82  }
    83  
    84  // Join joins the parts with the separator.
    85  // Will keep the first part prefix separator (if found) and the last part suffix separator optional.
    86  func Join(sep string, parts ...string) string {
    87  	var s string
    88  	for i, part := range parts {
    89  		// remove prefix sep if not first
    90  		if i != 0 {
    91  			part = strings.TrimPrefix(part, sep)
    92  		}
    93  		s += part
    94  		// if not last part, make sure we have a suffix sep
    95  		if i != len(parts)-1 && !strings.HasSuffix(part, sep) {
    96  			s += sep
    97  		}
    98  	}
    99  	return s
   100  }
   101  
   102  func IsHidden(pth, sep, prefix string) bool {
   103  	for pth != "" {
   104  		parsed := Parse(pth, sep)
   105  		if strings.HasPrefix(parsed["base_name"], prefix) {
   106  			return true
   107  		}
   108  		pth = parsed["parent"]
   109  	}
   110  	return false
   111  }
   112  
   113  func isHidden(l *lua.State) int {
   114  	p := lua.CheckString(l, 1)
   115  	sep := SEPARATOR
   116  	if !l.IsNone(2) {
   117  		sep = lua.CheckString(l, 2)
   118  	}
   119  	prefix := HiddenPrefix
   120  	if !l.IsNone(3) {
   121  		prefix = lua.CheckString(l, 3)
   122  	}
   123  	l.PushBoolean(IsHidden(p, sep, prefix))
   124  	return 1
   125  }