Skip to content
Snippets Groups Projects
Commit 5120dea1 authored by Md. Alim Ul Karim's avatar Md. Alim Ul Karim :speech_balloon:
Browse files

Merge branch 'feature/29-remove-filemode-and-osfilemode-to-filemode' into 'develop'

Resolve "Remove filemode and osfilemode to filemode"

Closes #29

See merge request !42
parents 9cf828d4 644eada4
Branches release/v0.3.9
Tags v0.3.9
1 merge request!42Resolve "Remove filemode and osfilemode to filemode"
package filemode
// 1 - Execute true
// 2 - Write true
// 3 - Write + Execute true
// 4 - Read true
// 5 - Read + Execute true
// 6 - Read + Write true
// 7 - Read + Write + Execute all true
type AttrVariant byte
//goland:noinspection ALL
const (
Execute AttrVariant = 1
Write AttrVariant = 2
WriteExecute AttrVariant = 3
Read AttrVariant = 4
ReadExecute AttrVariant = 5
ReadWrite AttrVariant = 6
ReadWriteExecute AttrVariant = 7
)
// v > byte(attrVariant)
func (attrVariant AttrVariant) IsGreaterThan(v byte) bool {
return v > byte(attrVariant)
}
func (attrVariant AttrVariant) String() string {
return string(attrVariant)
}
func (attrVariant AttrVariant) Value() byte {
return byte(attrVariant)
}
func (attrVariant AttrVariant) ToAttribute() Attribute {
return NewAttributeUsingVariant(attrVariant)
}
package filemode
import (
"gitlab.com/evatix-go/core/conditional"
"gitlab.com/evatix-go/core/constants"
)
type Attribute struct {
IsRead bool
IsWrite bool
IsExecute bool
}
func (attribute Attribute) ToAttributeValue() AttributeValue {
read, write, exe, sum := attribute.ToSpecificBytes()
return AttributeValue{
Read: read,
Write: write,
Execute: exe,
Sum: sum,
}
}
func (attribute Attribute) ToSpecificBytes() (read, write, exe, sum byte) {
read = conditional.Byte(attribute.IsRead, readValue, constants.Zero)
write = conditional.Byte(attribute.IsWrite, writeValue, constants.Zero)
exe = conditional.Byte(attribute.IsExecute, executeValue, constants.Zero)
return read, write, exe, read + write + exe
}
func (attribute Attribute) ToByte() byte {
r := conditional.Byte(attribute.IsRead, readValue, constants.Zero)
w := conditional.Byte(attribute.IsWrite, writeValue, constants.Zero)
e := conditional.Byte(attribute.IsExecute, executeValue, constants.Zero)
return r + w + e
}
func (attribute Attribute) ToSum() byte {
return attribute.ToByte()
}
func (attribute Attribute) ToRwx() [3]byte {
return [3]byte{
conditional.Byte(attribute.IsRead, readChar, constants.HyphenChar),
conditional.Byte(attribute.IsWrite, writeChar, constants.HyphenChar),
conditional.Byte(attribute.IsExecute, executeChar, constants.HyphenChar),
}
}
func (attribute Attribute) ToRwxString() string {
rwxBytes := attribute.ToRwx()
return string(rwxBytes[:])
}
func (attribute Attribute) ToVariant() AttrVariant {
b := attribute.ToByte()
return AttrVariant(b)
}
func (attribute Attribute) ToChar() byte {
return attribute.ToByte() + constants.ZeroChar
}
package filemode
type AttributeValue struct {
Read, Write, Execute, Sum byte
}
package filemode
type Variant string
//goland:noinspection ALL
const (
AllRead Variant = "444"
AllWrite Variant = "222"
AllExecute Variant = "111"
AllReadWrite Variant = "666"
AllReadExecute Variant = "555"
AllWriteExecute Variant = "333"
OwnerAllReadWriteGroupOther Variant = "755"
ReadWriteOwnerReadGroupOther Variant = "644"
ReadWriteOwnerReadExecuteGroupOther Variant = "655"
All Variant = "777"
)
func (variant Variant) String() string {
return string(variant)
}
func (variant Variant) ToWrapper() (Wrapper, error) {
return NewUsingVariant(variant)
}
package filemode
import (
"os"
"strconv"
"gitlab.com/evatix-go/core/constants"
)
type Wrapper struct {
Owner, Group, Other Attribute
}
// return rwx, (Owner)(Group)(Other) byte values under 1-7
func (wrapper Wrapper) Bytes() [3]byte {
// # https://play.golang.org/p/dX-wsvJmFie
owner := wrapper.Owner.ToSum()
group := wrapper.Group.ToSum()
other := wrapper.Other.ToSum()
allBytes := [3]byte{owner, group, other}
return allBytes
}
func (wrapper Wrapper) ToUint32Octal() uint32 {
// # https://play.golang.org/p/dX-wsvJmFie
str := wrapper.ToFileModeString()
// # https://bit.ly/35aBepk
octal, err := strconv.ParseUint(str, 8, 32)
if err != nil {
panic(err)
}
return uint32(octal)
}
// return 0rwx, '0'(Owner + '0')(Group + '0')(Other + '0')
// eg. 0777, 0555, 0755 NOT 0rwx
func (wrapper Wrapper) Chars() [4]byte {
// # https://play.golang.org/p/dX-wsvJmFie
owner := wrapper.Owner.ToChar()
group := wrapper.Group.ToChar()
other := wrapper.Other.ToChar()
allBytes := [4]byte{constants.ZeroChar, owner, group, other}
return allBytes
}
// 4 digit string 0rwx, example 0777
func (wrapper Wrapper) ToFileModeString() string {
// # https://play.golang.org/p/dX-wsvJmFie
allBytes := wrapper.Chars()
return string(allBytes[:])
}
// 3 digit string, example 777
func (wrapper Wrapper) ToModeStr() string {
// # https://play.golang.org/p/dX-wsvJmFie
allBytes := wrapper.Chars()
return string(allBytes[1:])
}
// returns "-rwxrwxrwx"
func (wrapper Wrapper) ToRwxes() string {
owner := wrapper.Owner.ToRwxString()
group := wrapper.Group.ToRwxString()
other := wrapper.Other.ToRwxString()
// # https://ss64.com/bash/chmod.html, needs to be 10 always
return constants.Hyphen + owner + group + other
}
func (wrapper Wrapper) ToRwxesChars() []byte {
str := wrapper.ToRwxes()
chars := []byte(str)
return chars
}
func (wrapper Wrapper) String() string {
// # https://ss64.com/bash/chmod.html, needs to be 10 always
return wrapper.ToRwxes()
}
func (wrapper Wrapper) ToFileMode() os.FileMode {
// # https://play.golang.org/p/dX-wsvJmFie
octalUint32 := wrapper.ToUint32Octal()
return os.FileMode(octalUint32)
}
func (wrapper Wrapper) ApplyChmod(fileOrDirectoryPath string) error {
return os.Chmod(fileOrDirectoryPath, wrapper.ToFileMode())
}
func (wrapper Wrapper) MustApplyChmod(fileOrDirectoryPath string) {
err := os.Chmod(fileOrDirectoryPath, wrapper.ToFileMode())
if err != nil {
panic(err)
}
}
package filemode
import "gitlab.com/evatix-go/core/msgtype"
//goland:noinspection GoUnusedExportedFunction
func NewAttribute(isRead, isWrite, isExecute bool) Attribute {
return Attribute{
IsRead: isRead,
IsWrite: isWrite,
IsExecute: isExecute,
}
}
// Length must be 3
// "rwx" should be put for attributes.
// eg. read enable all disable : "r--"
// eg. write enable all disable : "-w-"
// eg. execute enable all disable : "--x"
// eg. all enabled : "rwx"
func NewAttributeUsingRwx(rwx string) Attribute {
length := len(rwx)
if length != supportedLength {
panic(msgtype.
LengthShouldBeEqualToMessage.
Combine(
"rwx length should be "+supportedLengthString,
length))
}
r := rwx[0]
w := rwx[1]
e := rwx[2]
return Attribute{
IsRead: r == readChar,
IsWrite: w == writeChar,
IsExecute: e == executeChar,
}
}
// 1 - Execute true
// 2 - Write true
// 3 - Write + Execute true
// 4 - Read true
// 5 - Read + Execute true
// 6 - Read + Write true
// 7 - Read + Write + Execute all true
func NewAttributeUsingByte(v byte) Attribute {
if ReadWriteExecute.IsGreaterThan(v) {
msg := msgtype.
ShouldBeLessThanEqualMessage.
Combine(
"v byte should not be more than "+ReadWriteExecute.String(),
v)
panic(msg)
}
// TODO optimize logic in future.
/* isRead := (v & 0x04) != 0
isWrite := (v & 0x02) != 0
isExec := (v & 0x01) != 0
*/
isRead := v >= readValue
isWrite := (isRead && v >= readWriteValue) || (!isRead && v >= writeValue)
isExecute := (isWrite && isRead && v >= readWriteExecuteValue) ||
(isRead && !isWrite && v >= readExecuteValue) ||
(isWrite && !isRead && v >= writeExecuteValue) ||
(!isRead && !isWrite && v >= executeValue)
return Attribute{
IsRead: isRead,
IsWrite: isWrite,
IsExecute: isExecute,
}
}
func NewAttributeUsingVariant(v AttrVariant) Attribute {
return NewAttributeUsingByte(v.Value())
}
package filemode
// Reference : https://ss64.com/bash/chmod.html
const (
supportedLengthString = "3"
supportedLength = 3
readValue = 4
writeValue = 2
executeValue = 1
readWriteValue = readValue + writeValue
readExecuteValue = readValue + executeValue
writeExecuteValue = writeValue + executeValue
readWriteExecuteValue = readValue + writeValue + executeValue
ownerIndex = 0
groupIndex = 1
otherIndex = 2
readChar byte = 'r'
writeChar byte = 'w'
executeChar byte = 'x'
)
package osfilemode
package filemode
import "os"
......
package filemode
import (
"os"
"gitlab.com/evatix-go/core/constants"
"gitlab.com/evatix-go/core/msgtype"
)
// mode length needs to 3, not more not less
// mode chars should be digits only (0-7)
// example "777", "755", "655"
func New(mode string) (Wrapper, error) {
length := len(mode)
if length != supportedLength {
panic(msgtype.OutOfRangeLength.Combine(
"mode length should be "+supportedLengthString,
length))
}
allBytes := []byte(mode)
for i, allByte := range allBytes {
n := allByte - constants.ZeroChar
if n > 7 || n < 0 {
err := msgtype.
InvalidCharErrorMessage.
Error(
"mode char should be all digits and under 0 to 7",
n+constants.ZeroChar)
return Wrapper{}, err
}
allBytes[i] = n
}
return NewUsingByte(
allBytes[ownerIndex],
allBytes[groupIndex],
allBytes[otherIndex]), nil
}
// each byte should not be more than 7
func NewUsingBytes(allBytes [3]byte) Wrapper {
return NewUsingByte(
allBytes[ownerIndex],
allBytes[groupIndex],
allBytes[otherIndex])
}
func NewUsingFileMode(fileMode os.FileMode) Wrapper {
str := fileMode.String()
// Reference : https://play.golang.org/p/Qq_rKl_pAqe
owner := str[1:4]
group := str[4:7]
other := str[7:10]
wrapper := Wrapper{
Owner: NewAttributeUsingRwx(owner),
Group: NewAttributeUsingRwx(group),
Other: NewAttributeUsingRwx(other),
}
return wrapper
}
// each byte should not be more than 7
func NewUsingByte(owner, group, other byte) Wrapper {
wrapper := Wrapper{
Owner: NewAttributeUsingByte(owner),
Group: NewAttributeUsingByte(group),
Other: NewAttributeUsingByte(other),
}
return wrapper
}
func NewUsingAttrVariants(owner, group, other AttrVariant) Wrapper {
wrapper := Wrapper{
Owner: NewAttributeUsingVariant(owner),
Group: NewAttributeUsingVariant(group),
Other: NewAttributeUsingVariant(other),
}
return wrapper
}
func NewUsingAttrs(owner, group, other Attribute) Wrapper {
wrapper := Wrapper{
Owner: owner,
Group: group,
Other: other,
}
return wrapper
}
// Format "rwxrwxrwx"
// eg. owener all enabled only "rwx------"
// length must be 9 always.
func NewUsingRwxes(rwxrwxrwx string) (Wrapper, error) {
length := len(rwxrwxrwx)
if length != 9 {
err := msgtype.
LengthShouldBeEqualToMessage.
Error("rwxrwxrwx length must be 9", length)
return Wrapper{}, err
}
owner := rwxrwxrwx[0:3]
group := rwxrwxrwx[3:6]
other := rwxrwxrwx[6:9]
wrapper := Wrapper{
Owner: NewAttributeUsingRwx(owner),
Group: NewAttributeUsingRwx(group),
Other: NewAttributeUsingRwx(other),
}
return wrapper, nil
}
func NewUsingVariant(variant Variant) (Wrapper, error) {
return New(variant.String())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment