Repository: dolthub/dolt
File: go/store/nbs/journal_inspect.go (Go)

Code before:
		logrus.Errorf("Error creating filtered journal file: %v", err)
		return 1
	}
	defer outputFile.Close()

	_, filteredRecords, exitStatus := filterJournalCore(buf, outputFile, filterRoots, filterChunks)
	if exitStatus != 0 {
		return exitStatus
	}

	if filteredRecords == 0 {
		logrus.Infof("No records matched the filter criteria. No changes made.")
		return 1
	}

	// Print shell commands to replace the journal file
	now := time.Now()
	dateString := now.Format("2006_01_02_150405")

	logrus.Infof("")
	logrus.Infof("Filtered file: %s", outputPath)
	logrus.Infof("")
	logrus.Infof("To replace the original journal file, run these commands:")
	logrus.Infof("cp %s %s_saved_%s", journalPath, journalPath, dateString)
	logrus.Infof("mv %s %s", outputPath, journalPath)
	logrus.Infof("rm %s", filepath.Join(filepath.Dir(journalPath), "journal.idx"))

	return 0
}

// filterJournalCore performs the core filtering logic. It reads through the given journal data and writes all records
// except those matching the specified root and chunk hashes to the output writer.
//
// Returns the total number of records processed, the number of records filtered out, and an error if any.
func filterJournalCore(journalData []byte, output io.Writer, filterRoots, filterChunks []hash.Hash) (totalRecords int, filteredRecords int, exitStatus int) {
	// Create hash sets for faster lookups
	filterRootSet := hash.NewHashSet(filterRoots...)
	filterChunkSet := hash.NewHashSet(filterChunks...)

	for offset := 0; offset <= len(journalData)-4; {
		size := readUint32(journalData[offset:])
		if size == 0 {
			logrus.Errorf("Null bytes encountered at offset %d. filterJournal expects valid/truncated journal data. Extend as necessary", offset)
			return 0, 0, 1
		}
		if size >= journalWriterBuffSize {
			logrus.Errorf("Excessive length prefix found at offset %d. filterJournal expects valid/truncated journal data. Extend as necessary", offset)
			return 0, 0, 1
		}

		if offset+int(size) <= len(journalData) {

Review comment (suggestion):
I know this is all adhoc testing code and stuff, but this kinda UI affordance stuff really belongs outside of `nbs`. Better to return enough structure from this function for the command implementation to handle presentation.

Code after:
//
// Returns (FilterResult, exit code). Exit code is 0 on success, 1 on error.
func filterJournalFile(journalPath string, buf []byte, filterRoots, filterChunks []hash.Hash) (FilterResult, int) {
	dir := filepath.Dir(journalPath)
	base := filepath.Base(journalPath)
	outputPath := filepath.Join(dir, base+".filtered")

	outputFile, err := os.OpenFile(outputPath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0644)
	if err != nil {
		logrus.Errorf("Error creating filtered journal file: %v", err)
		return FilterResult{}, 1
	}
	defer outputFile.Close()

	_, filteredRecords, exitStatus := filterJournalCore(buf, outputFile, filterRoots, filterChunks)
	if exitStatus != 0 {
		return FilterResult{}, exitStatus
	}

	if filteredRecords == 0 {
		logrus.Infof("No records matched the filter criteria. No changes made.")
		return FilterResult{}, 0
	}

	return FilterResult{
		OutputPath:      outputPath,
		FilteredRecords: filteredRecords,
		OriginalPath:    journalPath,
	}, 0
}

// filterJournalCore performs the core filtering logic. It reads through the given journal data and writes all records
// except those matching the specified root and chunk hashes to the output writer.
//
// Returns the total number of records processed, the number of records filtered out, and an error if any.
func filterJournalCore(journalData []byte, output io.Writer, filterRoots, filterChunks []hash.Hash) (totalRecords int, filteredRecords int, exitStatus int) {
	// Create hash sets for faster lookups
	filterRootSet := hash.NewHashSet(filterRoots...)
	filterChunkSet := hash.NewHashSet(filterChunks...)

	for offset := 0; offset <= len(journalData)-4; {
		size := readUint32(journalData[offset:])
		if size == 0 {
			logrus.Errorf("Null bytes encountered at offset %d. filterJournal expects valid/truncated journal data. Extend as necessary", offset)
			return 0, 0, 1
		}
		if size >= journalWriterBuffSize {
			logrus.Errorf("Excessive length prefix found at offset %d. filterJournal expects valid/truncated journal data. Extend as necessary", offset)
			return 0, 0, 1
		}