code.gitea.io/gitea@v1.22.3/modules/git/object_format.go (about)

     1  // Copyright 2023 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package git
     5  
     6  import (
     7  	"crypto/sha1"
     8  	"crypto/sha256"
     9  	"regexp"
    10  	"strconv"
    11  )
    12  
    13  // sha1Pattern can be used to determine if a string is an valid sha
    14  var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
    15  
    16  // sha256Pattern can be used to determine if a string is an valid sha
    17  var sha256Pattern = regexp.MustCompile(`^[0-9a-f]{4,64}$`)
    18  
    19  type ObjectFormat interface {
    20  	// Name returns the name of the object format
    21  	Name() string
    22  	// EmptyObjectID creates a new empty ObjectID from an object format hash name
    23  	EmptyObjectID() ObjectID
    24  	// EmptyTree is the hash of an empty tree
    25  	EmptyTree() ObjectID
    26  	// FullLength is the length of the hash's hex string
    27  	FullLength() int
    28  	// IsValid returns true if the input is a valid hash
    29  	IsValid(input string) bool
    30  	// MustID creates a new ObjectID from a byte slice
    31  	MustID(b []byte) ObjectID
    32  	// ComputeHash compute the hash for a given ObjectType and content
    33  	ComputeHash(t ObjectType, content []byte) ObjectID
    34  }
    35  
    36  type Sha1ObjectFormatImpl struct{}
    37  
    38  var (
    39  	emptySha1ObjectID = &Sha1Hash{}
    40  	emptySha1Tree     = &Sha1Hash{
    41  		0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
    42  		0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
    43  	}
    44  )
    45  
    46  func (Sha1ObjectFormatImpl) Name() string { return "sha1" }
    47  func (Sha1ObjectFormatImpl) EmptyObjectID() ObjectID {
    48  	return emptySha1ObjectID
    49  }
    50  
    51  func (Sha1ObjectFormatImpl) EmptyTree() ObjectID {
    52  	return emptySha1Tree
    53  }
    54  func (Sha1ObjectFormatImpl) FullLength() int { return 40 }
    55  func (Sha1ObjectFormatImpl) IsValid(input string) bool {
    56  	return sha1Pattern.MatchString(input)
    57  }
    58  
    59  func (Sha1ObjectFormatImpl) MustID(b []byte) ObjectID {
    60  	var id Sha1Hash
    61  	copy(id[0:20], b)
    62  	return &id
    63  }
    64  
    65  // ComputeHash compute the hash for a given ObjectType and content
    66  func (h Sha1ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID {
    67  	hasher := sha1.New()
    68  	_, _ = hasher.Write(t.Bytes())
    69  	_, _ = hasher.Write([]byte(" "))
    70  	_, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10)))
    71  	_, _ = hasher.Write([]byte{0})
    72  	_, _ = hasher.Write(content)
    73  	return h.MustID(hasher.Sum(nil))
    74  }
    75  
    76  type Sha256ObjectFormatImpl struct{}
    77  
    78  var (
    79  	emptySha256ObjectID = &Sha256Hash{}
    80  	emptySha256Tree     = &Sha256Hash{
    81  		0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,
    82  		0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,
    83  		0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,
    84  		0x53, 0x21,
    85  	}
    86  )
    87  
    88  func (Sha256ObjectFormatImpl) Name() string { return "sha256" }
    89  func (Sha256ObjectFormatImpl) EmptyObjectID() ObjectID {
    90  	return emptySha256ObjectID
    91  }
    92  
    93  func (Sha256ObjectFormatImpl) EmptyTree() ObjectID {
    94  	return emptySha256Tree
    95  }
    96  func (Sha256ObjectFormatImpl) FullLength() int { return 64 }
    97  func (Sha256ObjectFormatImpl) IsValid(input string) bool {
    98  	return sha256Pattern.MatchString(input)
    99  }
   100  
   101  func (Sha256ObjectFormatImpl) MustID(b []byte) ObjectID {
   102  	var id Sha256Hash
   103  	copy(id[0:32], b)
   104  	return &id
   105  }
   106  
   107  // ComputeHash compute the hash for a given ObjectType and content
   108  func (h Sha256ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID {
   109  	hasher := sha256.New()
   110  	_, _ = hasher.Write(t.Bytes())
   111  	_, _ = hasher.Write([]byte(" "))
   112  	_, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10)))
   113  	_, _ = hasher.Write([]byte{0})
   114  	_, _ = hasher.Write(content)
   115  	return h.MustID(hasher.Sum(nil))
   116  }
   117  
   118  var (
   119  	Sha1ObjectFormat   ObjectFormat = Sha1ObjectFormatImpl{}
   120  	Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl{}
   121  )
   122  
   123  func ObjectFormatFromName(name string) ObjectFormat {
   124  	for _, objectFormat := range DefaultFeatures().SupportedObjectFormats {
   125  		if name == objectFormat.Name() {
   126  			return objectFormat
   127  		}
   128  	}
   129  	return nil
   130  }
   131  
   132  func IsValidObjectFormat(name string) bool {
   133  	return ObjectFormatFromName(name) != nil
   134  }