func (img *Image) Pin(kind MediaKind) bool {
	basename := fmt.Sprintf("%s.%s", img.Handle, "jpg")
	dataPath := Repository.dataPath(img.Source, basename)
	if dataPath == "" {
		panic(fmt.Errorf("missing dataPath for image '%s'", img.Handle))
	}

	// extract file name, kind, and camera/source using our convention
	chunks := strings.Split(dataPath, string(os.PathSeparator))
	if len(chunks) < 4 {
		panic(fmt.Errorf("impossible disk path '%s'", dataPath))
	}
	file := chunks[len(chunks)-1]
	prefix := chunks[len(chunks)-2]
	diskKind := chunks[len(chunks)-3]
	camera := chunks[len(chunks)-4]
	if file == "" || prefix == "" || diskKind != MediaData || camera == "" || camera != img.Source {
		panic(fmt.Errorf("missing file/kind/camera '%s'/'%s'/'%s'", file, kind, camera))
	}

	// compute the new disk location; start with directory
	destDir := Repository.dirFor(camera, kind)

	// use the same extension (so that a .jpg remains a .jpg etc.)
	chunks = strings.SplitN(file, ".", 2)
	if len(chunks) != 2 {
		panic(fmt.Errorf("unable to decompose filename '%s'", file))
	}

	// now we can construct the fully qualified destination filename, and link it
	destFile := Repository.canonFile(filepath.Join(destDir, fmt.Sprintf("%s.%s", img.Handle, chunks[1])))
	fi, err := os.Stat(destFile)
	if err != nil {
		if !os.IsNotExist(err) {
			panic(err)
		}
	}
	if fi == nil {
		if err := os.Symlink(dataPath, destFile); err != nil {
			panic(err)
		}
	} else {
		log.Debug("Image.Pin", "double pin of '%s' to '%s'", img.Handle, kind)
		return false
	}

	// also link the video adjunct, if there is one
	basename = fmt.Sprintf("%s.%s", img.Handle, "webm")
	dataPath = Repository.dataPath(img.Source, basename)
	fi, err = os.Stat(dataPath)
	if err != nil && !os.IsNotExist(err) {
		panic(err)
	}
	if !os.IsNotExist(err) && fi != nil {

	}
	destFile = Repository.canonFile(filepath.Join(destDir, basename))
	if err := os.Symlink(dataPath, destFile); err != nil {
		panic(err)
	}
	return true
}
// Pin sets the Image to be pinned. `kind` must be one of the `Media*` enum constants. This is a
// link operation, not a copy or move. As most Kinds are subject to periodic purging, it is not
// necessary to unpin them; actual bytes are kept around as long as the image is
// pinned as at least one Kind.
//
// Images are expected to be created and media (if any) linked, before pinning.
// Pinning before linking video will result in the video media not being pinned
// or retained (but the image will be.)
//
// Returns true if the item was pinned, or false if it was already pinned.
Pin sets the Image to be pinned. `kind` must be one of the `Media*` enum constants. This is a
link operation, not a copy or move. As most Kinds are subject to periodic purging, it is not
necessary to unpin them; actual bytes are kept around as long as the image is
pinned as at least one Kind.

Images are expected to be created and media (if any) linked, before pinning.
Pinning before linking video will result in the video media not being pinned
or retained (but the image will be.)

Returns true if the item was pinned, or false if it was already pinned.
// Pin sets the Image to be pinned . ` kind ` must be one of the ` Media * ` enum constants . This is a // link operation not a copy or move . As most Kinds are subject to periodic purging it is not // necessary to unpin them ; actual bytes are kept around as long as the image is // pinned as at least one Kind . // // Images are expected to be created and media ( if any ) linked before pinning . // Pinning before linking video will result in the video media not being pinned // or retained ( but the image will be . ) // // Returns true if the item was pinned or false if it was already pinned .
func (img *Image) Pin(kind MediaKind) bool {
	basename := fmt.Sprintf("%s.%s", img.Handle, "jpg")
	dataPath := Repository.dataPath(img.Source, basename)
	if dataPath == "" {
		panic(fmt.Errorf("missing dataPath for image '%s'", img.Handle))
	}
	chunks := strings.Split(dataPath, string(os.PathSeparator))
	if len(chunks) < 4 {
		panic(fmt.Errorf("impossible disk path '%s'", dataPath))
	}
	file := chunks[len(chunks)-1]
	prefix := chunks[len(chunks)-2]
	diskKind := chunks[len(chunks)-3]
	camera := chunks[len(chunks)-4]
	if file == "" || prefix == "" || diskKind != MediaData || camera == "" || camera != img.Source {
		panic(fmt.Errorf("missing file/kind/camera '%s'/'%s'/'%s'", file, kind, camera))
	}
	destDir := Repository.dirFor(camera, kind)
	chunks = strings.SplitN(file, ".", 2)
	if len(chunks) != 2 {
		panic(fmt.Errorf("unable to decompose filename '%s'", file))
	}
	destFile := Repository.canonFile(filepath.Join(destDir, fmt.Sprintf("%s.%s", img.Handle, chunks[1])))
	fi, err := os.Stat(destFile)
	if err != nil {
		if !os.IsNotExist(err) {
			panic(err)
		}
	}
	if fi == nil {
		if err := os.Symlink(dataPath, destFile); err != nil {
			panic(err)
		}
	} else {
		log.Debug("Image.Pin", "double pin of '%s' to '%s'", img.Handle, kind)
		return false
	}
	basename = fmt.Sprintf("%s.%s", img.Handle, "webm")
	dataPath = Repository.dataPath(img.Source, basename)
	fi, err = os.Stat(dataPath)
	if err != nil && !os.IsNotExist(err) {
		panic(err)
	}
	if !os.IsNotExist(err) && fi != nil {
	}
	destFile = Repository.canonFile(filepath.Join(destDir, basename))
	if err := os.Symlink(dataPath, destFile); err != nil {
		panic(err)
	}
	return true
}
func ( img * Image ) Pin ( kind MediaKind ) bool { basename := fmt . Sprintf ( " " , img . Handle , " " ) dataPath := Repository . dataPath ( img . Source , basename ) if dataPath == " " { panic ( fmt . Errorf ( " " , img . Handle ) ) } chunks := strings . Split ( dataPath , string ( os . PathSeparator ) ) if len ( chunks ) < 4 { panic ( fmt . Errorf ( " " , dataPath ) ) } file := chunks [ len ( chunks ) - 1 ] prefix := chunks [ len ( chunks ) - 2 ] diskKind := chunks [ len ( chunks ) - 3 ] camera := chunks [ len ( chunks ) - 4 ] if file == " " || prefix == " " || diskKind != MediaData || camera == " " || camera != img . Source { panic ( fmt . Errorf ( " " , file , kind , camera ) ) } destDir := Repository . dirFor ( camera , kind ) chunks = strings . SplitN ( file , " " , 2 ) if len ( chunks ) != 2 { panic ( fmt . Errorf ( " " , file ) ) } destFile := Repository . canonFile ( filepath . Join ( destDir , fmt . Sprintf ( " " , img . Handle , chunks [ 1 ] ) ) ) fi , err := os . Stat ( destFile ) if err != nil { if ! os . IsNotExist ( err ) { panic ( err ) } } if fi == nil { if err := os . Symlink ( dataPath , destFile ) ; err != nil { panic ( err ) } } else { log . Debug ( " " , " " , img . Handle , kind ) return false } basename = fmt . Sprintf ( " " , img . Handle , " " ) dataPath = Repository . dataPath ( img . Source , basename ) fi , err = os . Stat ( dataPath ) if err != nil && ! os . IsNotExist ( err ) { panic ( err ) } if ! os . IsNotExist ( err ) && fi != nil { } destFile = Repository . canonFile ( filepath . Join ( destDir , basename ) ) if err := os . Symlink ( dataPath , destFile ) ; err != nil { panic ( err ) } return true }
Pin sets the Image to be pinned.
Pin sets the Image to be pinned .
// extract file name, kind, and camera/source using our convention // compute the new disk location; start with directory // use the same extension (so that a .jpg remains a .jpg etc.) // now we can construct the fully qualified destination filename, and link it // also link the video adjunct, if there is one