 }
 
 extension NSURLSession {
-	/// Returns a signal that will download a file using the given request. The
-	/// file will be deleted after the URL has been sent upon the signal.
-	internal func carthage_downloadWithRequest(request: NSURLRequest) -> ColdSignal<(NSURL, NSURLResponse)> {
-		return ColdSignal { (sink, disposable) in
+	/// Returns a producer that will download a file using the given request. The
+	/// file will be deleted after the producer terminates.
+	internal func carthage_downloadWithRequest(request: NSURLRequest) -> SignalProducer<(NSURL, NSURLResponse), NSError> {
+		return SignalProducer { observer, disposable in
 			let serialDisposable = SerialDisposable()
 			let handle = disposable.addDisposable(serialDisposable)
 

	/// Creates a directory enumerator at the given URL. Sends each URL
	/// enumerated, along with the enumerator itself (so it can be introspected
	/// and modified as enumeration progresses).
	public func carthage_enumeratorAtURL(URL: NSURL, includingPropertiesForKeys keys: [String], options: NSDirectoryEnumerationOptions, catchErrors: Bool = false) -> ColdSignal<(NSDirectoryEnumerator, NSURL)> {
		return ColdSignal { (sink, disposable) in
			let enumerator = self.enumeratorAtURL(URL, includingPropertiesForKeys: keys, options: options) { (URL, error) in
				if catchErrors {
					return true
				} else {
					sink.put(.Error(error ?? CarthageError.ReadFailed(URL).error))
					return false
				}
			}!

	return result
}

/// Sends each value that occurs on `signal` combined with each value that
/// occurs on `otherSignal` (repeats included).
internal func permuteWith<T, U, E>(otherSignal: Signal<U, E>)(signal: Signal<T, E>) -> Signal<(T, U), E> {
	return Signal { observer in
		let lock = NSRecursiveLock()
		lock.name = "org.carthage.CarthageKit.permuteWith"

		var signalValues: [T] = []
		var signalCompleted = false
		var otherValues: [U] = []
		var otherCompleted = false

		let signalDisposable = signal.observe(next: { value in
			lock.lock()

			signalValues.append(value)
			for otherValue in otherValues {
				sendNext(observer, (value, otherValue))
			}

			lock.unlock()
		}, error: { error in
			sendError(observer, error)
		}, completed: {
			lock.lock()

			signalCompleted = true
			if otherCompleted {
				sendCompleted(observer)
			}

			lock.unlock()
		}, interrupted: {
			sendInterrupted(observer)
		})

		let otherDisposable = otherSignal.observe(next: { value in
			lock.lock()

			otherValues.append(value)
			for signalValue in signalValues {
				sendNext(observer, (signalValue, value))
			}

			lock.unlock()
		}, error: { error in
			sendError(observer, error)
		}, completed: {
			lock.lock()

			otherCompleted = true
			if signalCompleted {
				sendCompleted(observer)
			}

			lock.unlock()
		}, interrupted: {
			sendInterrupted(observer)
		})

		let compositeDisposable = CompositeDisposable()
		compositeDisposable.addDisposable(signalDisposable)
		compositeDisposable.addDisposable(otherDisposable)
		return compositeDisposable
	}
}

/// Sends each value that occurs on `producer` combined with each value that
/// occurs on `otherProducer` (repeats included).
internal func permuteWith<T, U, E>(otherProducer: SignalProducer<U, E>)(producer: SignalProducer<T, E>) -> SignalProducer<(T, U), E> {
	return producer.lift(permuteWith)(otherProducer)
}

/// Dematerializes the signal, like dematerialize(), but only yields Error
/// events if no values were sent.
internal func dematerializeErrorsIfEmpty<T, E>(signal: Signal<Event<T, E>, NoError>) -> Signal<T, E> {
	return Signal { observer in
		var receivedValue = false
		var receivedError: E? = nil

		return signal.observe(next: { event in
			switch event {
			case let .Next(value):
				receivedValue = true
				sendNext(observer, value.unbox)

			case let .Error(error):
				receivedError = error.unbox

			case .Completed:
				sendCompleted(observer)

			case .Interrupted:
				sendInterrupted(observer)
			}
		}, completed: {
			if !receivedValue {
				if let receivedError = receivedError {
					sendError(observer, receivedError)
				}
			}

			sendCompleted(observer)
		}, interrupted: {
			sendInterrupted(observer)
		})
	}
}

/// Sends all permutations of the values from the input producers, as they arrive.
///
/// If no input producers are given, sends a single empty array then completes.
internal func permutations<T, E>(producers: [SignalProducer<T, E>]) -> SignalProducer<[T], E> {
	var combined: SignalProducer<[T], E> = SignalProducer(value: [])

	for producer in producers {
		combined = combined
			|> permuteWith(producer)
			|> map { (var array, value) in
				array.append(value)
				return array
			}
	}

	return combined
