#! /usr/bin/racket
#|
 | Copyright © 2013 Kenneth Graunke <kenneth@whitecape.org>
 |
 | Permission is hereby granted, free of charge, to any person obtaining a
 | copy of this software and associated documentation files (the "Software"),
 | to deal in the Software without restriction, including without limitation
 | the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | and/or sell copies of the Software, and to permit persons to whom the
 | Software is furnished to do so, subject to the following conditions:
 |
 | The above copyright notice and this permission notice (including the next
 | paragraph) shall be included in all copies or substantial portions of the
 | Software.
 |
 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | DEALINGS IN THE SOFTWARE.
 |#

#lang racket
(require file/sha1)
(require racket/set)

; [filename]
; [(filename, sha1sum)]
; [

; filename -> (sha1sum . filename)
(define (make-sha1-pair filename)
  (cons (call-with-input-file filename sha1) filename))

; Convert an association list containing duplicate keys to a
; hash table mapping from keys -> list of values.
; 
; For example:
; '((a . "apple") (b . "banana") (b . "bonus"))
; becomes:
; #hash((b . ("bonus banana")) (a . ("apple")))
(define (bagify assocs)
  (foldl (lambda (pair ht)
           (hash-update ht
                        (car pair)
                        (curry cons (cdr pair))
                        '()))
         #hash() assocs))

; list -> bag
(define (make-sha1bag files)
  (hash->list (bagify (map make-sha1-pair files))))

; True if (length x) > 2
(define (two-or-more? x) (and (not (empty? x)) (not (empty? (cdr x)))))

; bag ->
(define files (current-command-line-arguments))
;(define files '#("/tmp/hi" "/tmp/there" "/tmp/hello"))
(define sha1bag (make-sha1bag (vector->list files)))

(define dups (filter two-or-more? (map cdr sha1bag)))

(for-each (lambda (x)
            (display "Duplicates:")
            (newline)
            (for-each (lambda (x)
                        (display "- ")
                        (display x)
                        (newline))
                      x)
            (newline))
          dups)

(for-each (lambda (x)
            (display "rm ")
            (for-each (lambda (x)
                        (display x)
                        (display " "))
                      (cdr x))
            (newline))
          dups)
