code: func (actor PushActorImpl) ProcessPath(dirOrZipFile string, f func(string) error) error {
  	if !actor.zipper.IsZipFile(dirOrZipFile) {
  		if filepath.IsAbs(dirOrZipFile) {
  			appDir, err := filepath.EvalSymlinks(dirOrZipFile)
  			if err != nil {
  				return err
  			}
  			err = f(appDir)
  			if err != nil {
  				return err
  			}
  		} else {
  			absPath, err := filepath.Abs(dirOrZipFile)
  			if err != nil {
  				return err
  			}
  			appDir, err := filepath.EvalSymlinks(absPath)
  			if err != nil {
  				return err
  			}
  
  			err = f(appDir)
  			if err != nil {
  				return err
  			}
  		}
  
  		return nil
  	}
  
  	tempDir, err := ioutil.TempDir("", "unzipped-app")
  	if err != nil {
  		return err
  	}
  
  	err = actor.zipper.Unzip(dirOrZipFile, tempDir)
  	if err != nil {
  		return err
  	}
  
  	err = f(tempDir)
  	if err != nil {
  		return err
  	}
  
  	err = os.RemoveAll(tempDir)
  	if err != nil {
  		return err
  	}
  
  	return nil
  }
docs: // ProcessPath takes in a director of app files or a zip file which contains
  // the app files. If given a zip file, it will extract the zip to a temporary
  // location, call the provided callback with that location, and then clean up
  // the location after the callback has been executed.
  //
  // This was done so that the caller of ProcessPath wouldn't need to know if it
  // was a zip file or an app dir that it was given, and the caller would not be
  // responsible for cleaning up the temporary directory ProcessPath creates when
  // given a zip.