Ejemplo n.º 1
0
func Log(c *cli.Context) {
	db := util.OpenDB()
	defer db.Close()

	yellow := ansi.ColorFunc("yellow+h:black")

	// Perform operations in a read-only lock
	db.View(func(tx *bolt.Tx) error {
		info := tx.Bucket(util.INFO)
		objects := tx.Bucket(util.OBJECTS)
		headsBytes := info.Get(util.HEADS)

		if headsBytes != nil {
			queue := types.DeserializeHashes(headsBytes)

			// TODO: Keep a visited set, so we don't repeat commits

			for len(queue) > 0 {
				i := GetNewestCommit(objects, queue)

				// Get commit and remove it from the priority queue
				commitSha := queue[i]
				commit := types.DeserializeCommitObject(objects.Get(commitSha))
				queue = append(queue[:i], queue[i+1:]...)

				fmt.Printf(yellow("commit %s\n"), commitSha)
				fmt.Printf("Message: %s\n", commit.Message)
				fmt.Printf("Author: %s\n", commit.Author)
				fmt.Printf("Date: %s\n", commit.Time)

				if len(commit.Parents) > 0 {
					fmt.Printf("Parents: %s\n", commit.Parents)
				}

				fmt.Printf("Tree: %s\n", commit.Tree)
				fmt.Println()

				// Append parents of this commit to the queue
				queue = append(queue, commit.Parents...)
			}

			return nil
		}

		fmt.Println("There are no commits in this repository...")
		return nil
	})
}
Ejemplo n.º 2
0
// Commit implements `got commit`
func Commit(c *cli.Context) {
	db := util.OpenDB()
	defer db.Close()

	if len(c.String("message")) == 0 {
		log.Fatalln("Must supply a commit message.")
	}

	if len(c.String("author")) == 0 {
		log.Fatalln("Must supply a commit author.")
	}

	// Perform operations in a write lock
	err := db.Update(func(tx *bolt.Tx) error {
		info := tx.Bucket(util.INFO)       // The bucket holding repositry metadata
		objects := tx.Bucket(util.OBJECTS) // The bucket holding got objects
		current := info.Get(util.CURRENT)

		// Create a commit object from the current directory snapshot
		util.DebugLog("Taking snapshot of repo...")
		hash := TakeSnapshot(tx.Bucket(util.OBJECTS), ".")
		util.DebugLog("Repo snapshot has hash " + hash.String() + ".")

		commit := types.CommitObject{
			Author:  c.String("author"),
			Message: c.String("message"),
			Time:    time.Now(),
			Tree:    hash,
			Parents: make([]types.Hash, 0),
		}

		// There is a 'current' commit, then it is the parent of the new commit
		if current != nil {
			commit.Parents = append(commit.Parents, current)
		}

		commitBytes := commit.Serialize()
		commitSha := types.CalculateHash(commitBytes)
		objects.Put(commitSha, commitBytes)
		util.DebugLog("Created commit of sha " + commitSha.String() + ".")

		// CURRENT now corresponds to the commit that we just created
		info.Put(util.CURRENT, commitSha)

		// Update heads
		headsBytes := info.Get(util.HEADS)
		if headsBytes != nil {
			heads := types.DeserializeHashes(headsBytes)
			util.DebugLog("Currently " + strconv.Itoa(len(heads)) + " heads in this repo...")

			// Remove current, if it is a head
			for i, head := range heads {
				if head.Equal(current) {
					heads = append(heads[:i], heads[i+1:]...)
					break
				}
			}

			// Add the new commit as a head
			heads = append(heads, commitSha)

			info.Put(util.HEADS, types.SerializeHashes(heads))
		} else {
			util.DebugLog("Currently no heads in this repo. Putting HEADS: " + fmt.Sprint(([]types.Hash{commitSha})))
			info.Put(util.HEADS, types.SerializeHashes([]types.Hash{commitSha}))
		}

		return nil
	})
	if err != nil {
		log.Fatal("Error reading from the database.")
	}
}