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

Code before:
		m.fmut.RUnlock()
		if !ok {
			// Shouldn't happen because !cfg.Paused, but might happen
			// if the folder is about to be unpaused, but not yet.
			l.Debugln("ccH: no fset", folder.ID)
			indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
			continue
		}

		indexSenders.add(cfg, fs, ccDeviceInfos[folder.ID])

		// We might already have files that we need to pull so let the
		// folder runner know that it should recheck the index data.
		m.fmut.RLock()
		if runner := m.folderRunners[folder.ID]; runner != nil {
			defer runner.SchedulePull()
		}
		m.fmut.RUnlock()
	}

	indexSenders.removeAllExcept(seenFolders)
	// All current pending folders were touched above, so discard any with older timestamps
	if expired, err := m.db.RemovePendingFoldersBeforeTime(deviceID, handleTime); err != nil {
		l.Infof("Could not clean up pending folder entries: %v", err)
	} else if expired > 0 {
		m.evLogger.Log(events.ClusterPendingChanged, map[string]interface{}{
			"device": deviceID.String(),
			"count":  expired,
		})
	}

	return changed, tempIndexFolders, paused, nil
}

func (m *model) ccCheckEncryption(fcfg config.FolderConfiguration, folderDevice config.FolderDeviceConfiguration, ccDeviceInfos *indexSenderStartInfo, deviceUntrusted bool) error {
	hasTokenRemote := len(ccDeviceInfos.remote.EncryptionPasswordToken) > 0
	hasTokenLocal := len(ccDeviceInfos.local.EncryptionPasswordToken) > 0
	isEncryptedRemote := folderDevice.EncryptionPassword != ""
	isEncryptedLocal := fcfg.Type == config.FolderTypeReceiveEncrypted

	if !isEncryptedRemote && !isEncryptedLocal && deviceUntrusted {
		return errEncryptionNotEncryptedUntrusted
	}

	if !(hasTokenRemote || hasTokenLocal || isEncryptedRemote || isEncryptedLocal) {
		// Noone cares about encryption here
		return nil
	}

	if isEncryptedRemote && isEncryptedLocal {
		// Should never happen, but config racyness and be safe.

Review comment (suggestion):
I think this should also be emitted in places where we currently emit folder_rejected or device_rejected, to effectively have one event that represents all pending stuff changes, and in theory we should mark the other events for deprecation.

Code after:
			continue
		}

		if cfg.Paused {
			indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
			continue
		}

		if err := m.ccCheckEncryption(cfg, folderDevice, ccDeviceInfos[folder.ID], deviceCfg.Untrusted); err != nil {
			sameError := false
			if devs, ok := m.folderEncryptionFailures[folder.ID]; ok {
				sameError = devs[deviceID] == err
			} else {
				m.folderEncryptionFailures[folder.ID] = make(map[protocol.DeviceID]error)
			}
			m.folderEncryptionFailures[folder.ID][deviceID] = err
			msg := fmt.Sprintf("Failure checking encryption consistency with device %v for folder %v: %v", deviceID, cfg.Description(), err)
			if sameError || err == errEncryptionReceivedToken {
				l.Debugln(msg)
			} else {
				l.Warnln(msg)
			}

			return tempIndexFolders, paused, err
		}
		if devErrs, ok := m.folderEncryptionFailures[folder.ID]; ok {
			if len(devErrs) == 1 {
				delete(m.folderEncryptionFailures, folder.ID)
			} else {
				delete(m.folderEncryptionFailures[folder.ID], deviceID)
			}
		}

		// Handle indexes

		if !folder.DisableTempIndexes {
			tempIndexFolders = append(tempIndexFolders, folder.ID)
		}

		m.fmut.RLock()
		fs, ok := m.folderFiles[folder.ID]
		m.fmut.RUnlock()
		if !ok {
			// Shouldn't happen because !cfg.Paused, but might happen
			// if the folder is about to be unpaused, but not yet.
			l.Debugln("ccH: no fset", folder.ID)
			indexSenders.addPending(cfg, ccDeviceInfos[folder.ID])
			continue
		}

		indexSenders.add(cfg, fs, ccDeviceInfos[folder.ID])