Repository: syncthing/syncthing
File: lib/model/folder_sendrecv.go (Go)

Code before:
//                                |
//                                | pullChan (sharedPullerState)
//                                |
//                                |   +-----------------------+
//                                |   | +-----------------------+
//                                +-->| |                       |
//                                    | |     pullerRoutine     |
//                                    +-|                       |
//                                      +-----------------------+
//                                                  |
//                                                  | finisherChan (sharedPullerState)
//                                                  |
//                                                  |   +-----------------------+
//                                                  |   |                       |
//                                                  +-->|    finisherRoutine    | - - - - > ItemFinished
//                                                      |                       |
//                                                      +-----------------------+

// handleFile queues the copies and pulls as necessary for a single new or
// changed file.
func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, snap *db.Snapshot, copyChan chan<- copyBlocksState) {
	
	available := false
	for _, dev := range snap.Availability(file.Name) {
		if !f.model.IsFolderPausedOnDevice(f.folderID, dev) {
		available = true
		break
		}
	}

	if !available {
		f.newPullError(file.Name, fmt.Errorf("file not available on any connected device"))
		return
	}
	
	curFile, hasCurFile := snap.Get(protocol.LocalDeviceID, file.Name)

	have, _ := blockDiff(curFile.Blocks, file.Blocks)

	tempName := fs.TempName(file.Name)

	populateOffsets(file.Blocks)

	blocks := append([]protocol.BlockInfo{}, file.Blocks...)
	reused := make([]int, 0, len(file.Blocks))

	if f.Type != config.FolderTypeReceiveEncrypted {
		blocks, reused = f.reuseBlocks(blocks, reused, file, tempName)
	}

	// The sharedpullerstate will know which flags to use when opening the

Review comment (suggestion):
Where `handleFile` is called there's already a check for availability - would make sense to add the pause check there.

Code after:
//                                |   +-----------------------+
//                                |   | +-----------------------+
//                                +-->| |                       |
//                                    | |     pullerRoutine     |
//                                    +-|                       |
//                                      +-----------------------+
//                                                  |
//                                                  | finisherChan (sharedPullerState)
//                                                  |
//                                                  |   +-----------------------+
//                                                  |   |                       |
//                                                  +-->|    finisherRoutine    | - - - - > ItemFinished
//                                                      |                       |
//                                                      +-----------------------+

// handleFile queues the copies and pulls as necessary for a single new or
// changed file.
func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, snap *db.Snapshot, copyChan chan<- copyBlocksState) {
	curFile, hasCurFile := snap.Get(protocol.LocalDeviceID, file.Name)

	have, _ := blockDiff(curFile.Blocks, file.Blocks)

	tempName := fs.TempName(file.Name)

	populateOffsets(file.Blocks)

	blocks := append([]protocol.BlockInfo{}, file.Blocks...)
	reused := make([]int, 0, len(file.Blocks))

	if f.Type != config.FolderTypeReceiveEncrypted {
		blocks, reused = f.reuseBlocks(blocks, reused, file, tempName)
	}

	// The sharedpullerstate will know which flags to use when opening the
	// temp file depending if we are reusing any blocks or not.
	if len(reused) == 0 {
		// Otherwise, discard the file ourselves in order for the
		// sharedpuller not to panic when it fails to exclusively create a
		// file which already exists
		f.inWritableDir(f.mtimefs.Remove, tempName)
	}

	// Reorder blocks
	blocks = f.blockPullReorderer.Reorder(blocks)

	f.evLogger.Log(events.ItemStarted, map[string]string{
		"folder": f.folderID,
		"item":   file.Name,
		"type":   "file",
		"action": "update",
	})