• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

deadc0de6 / catcli / 4399176145

pending completion
4399176145

Pull #30

github

GitHub
Merge ee2cf80d9 into 7590ad02c
Pull Request #30: Fuse

474 of 474 new or added lines in 13 files covered. (100.0%)

1304 of 1691 relevant lines covered (77.11%)

3.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

26.47
/catcli/fuser.py
1
"""
2
author: deadc0de6 (https://github.com/deadc0de6)
3
Copyright (c) 2023, deadc0de6
4

5
fuse for catcli
6
"""
7

8
import os
5✔
9
from time import time
5✔
10
from stat import S_IFDIR, S_IFREG
5✔
11
from typing import List, Dict, Any, Optional
5✔
12
import fuse  # type: ignore
5✔
13

14
# local imports
15
from catcli.noder import Noder
5✔
16
from catcli.nodes import NodeTop, NodeAny
5✔
17
from catcli.utils import path_to_search_all, path_to_top
5✔
18
from catcli import nodes
5✔
19

20

21
class Fuser:
5✔
22
    """fuse filesystem mounter"""
23

24
    def __init__(self, mountpoint: str,
5✔
25
                 top: NodeTop,
26
                 noder: Noder,
27
                 debug: bool = False):
28
        """fuse filesystem"""
29
        filesystem = CatcliFilesystem(top, noder)
×
30
        fuse.FUSE(filesystem,
×
31
                  mountpoint,
32
                  foreground=debug,
33
                  allow_other=True,
34
                  nothreads=True,
35
                  debug=debug)
36

37

38
class CatcliFilesystem(fuse.LoggingMixIn, fuse.Operations):  # type: ignore
5✔
39
    """in-memory filesystem for catcli catalog"""
40

41
    def __init__(self, top: NodeTop,
5✔
42
                 noder: Noder):
43
        """init fuse filesystem"""
44
        self.top = top
×
45
        self.noder = noder
×
46

47
    def _get_entry(self, path: str) -> Optional[NodeAny]:
5✔
48
        """return the node pointed by path"""
49
        path = path_to_top(path)
×
50
        found = self.noder.list(self.top, path,
×
51
                                rec=False,
52
                                fmt='native',
53
                                raw=True)
54
        if found:
×
55
            return found[0]
×
56
        return None
×
57

58
    def _get_entries(self, path: str) -> List[NodeAny]:
5✔
59
        """return nodes pointed by path"""
60
        path = path_to_search_all(path)
×
61
        found = self.noder.list(self.top, path,
×
62
                                rec=False,
63
                                fmt='native',
64
                                raw=True)
65
        return found
×
66

67
    def _getattr(self, path: str) -> Dict[str, Any]:
5✔
68
        entry = self._get_entry(path)
×
69
        if not entry:
×
70
            return {}
×
71

72
        maccess = time()
×
73
        mode: Any = S_IFREG
×
74
        size: int = 0
×
75
        if entry.type == nodes.TYPE_ARCHIVED:
×
76
            mode = S_IFREG
×
77
            size = entry.size
×
78
        elif entry.type == nodes.TYPE_DIR:
×
79
            mode = S_IFDIR
×
80
            size = entry.size
×
81
            maccess = entry.maccess
×
82
        elif entry.type == nodes.TYPE_FILE:
×
83
            mode = S_IFREG
×
84
            size = entry.size
×
85
            maccess = entry.maccess
×
86
        elif entry.type == nodes.TYPE_STORAGE:
×
87
            mode = S_IFDIR
×
88
            size = entry.size
×
89
            maccess = entry.ts
×
90
        elif entry.type == nodes.TYPE_META:
×
91
            mode = S_IFREG
×
92
        elif entry.type == nodes.TYPE_TOP:
×
93
            mode = S_IFREG
×
94
        mode = mode | 0o777
×
95
        return {
×
96
            'st_mode': (mode),  # file type
97
            'st_nlink': 1,  # count hard link
98
            'st_size': size,
99
            'st_ctime': maccess,  # attr last modified
100
            'st_mtime': maccess,  # content last modified
101
            'st_atime': maccess,  # access time
102
            'st_uid': os.getuid(),
103
            'st_gid': os.getgid(),
104
        }
105

106
    def getattr(self, path: str, _fh: Any = None) -> Dict[str, Any]:
5✔
107
        """return attr of file pointed by path"""
108
        if path == '/':
×
109
            # mountpoint
110
            curt = time()
×
111
            meta = {
×
112
                'st_mode': (S_IFDIR | 0o777),
113
                'st_nlink': 1,
114
                'st_size': 0,
115
                'st_ctime': curt,
116
                'st_mtime': curt,
117
                'st_atime': curt,
118
                'st_uid': os.getuid(),
119
                'st_gid': os.getgid(),
120
            }
121
            return meta
×
122
        meta = self._getattr(path)
×
123
        return meta
×
124

125
    def readdir(self, path: str, _fh: Any) -> List[str]:
5✔
126
        """read directory content"""
127
        content = ['.', '..']
×
128
        entries = self._get_entries(path)
×
129
        for entry in entries:
×
130
            content.append(entry.name)
×
131
        return content
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc